Since 2015, JavaScript has improved immensely.
It’s much more pleasant to use it now than ever.
In this article, we’ll look at sets and WeakSets.
Set API
The Set
API has various methods we can use to let us manipulate it.
The constructor lets us pass in an iterable object and create a set from it.
For instance, we can write:
const set = new Set([1, 2, 3]);
to create a set from an array.
The Set.prototype.add
method takes a value and appends it to the set.
It returns the set with the new entry.
Set.prototype.has
takes a value and returns true
if it’s in the set and false
otherwise.
The Set.prototype.delete
method takes a value and lets us remove it.
It returns true
if it’s deleted and false
otherwise.
The Set.prototype.size
getter returns the number of items in the set.
The Set.prototype.clear
method lets us remove all items from a set.
Set.prototype.values
is a method that returns all values of a set as an iterator.
Set.prototype[Symbol.iterator]
returns an iterable object that lets us iterate over a set.
The Set.prototype.forEach
let takes a callback with the signature, (value, key, collection)
as the signature, and runs it for each item in the set,
value
has the set value.
key
has the same value as value
.
The collection
is the set itself.
The 2nd argument is the value of this
we use in the callback.
Sets also have the Set.prototype.entries
method to return an iterable object with each entry being a key-value array.
The key and value are the same.
The Set.prototype.keys
method returns us an iterable object with the keys, which is the same as the values.
WeakSet
A WeakSet is a set that doesn’t prevent its elements from being garbage collected.
It works like WeakMaps and doesn’t allow iteration, looping, or clearing.
There isn’t many uses cases for WeakSets.
We can add objects to them and then get them with the reference.
So we can write:
const weakSet = new WeakSet();
const obj = {};
weakSet.add(obj);
const hasObj = weakSet.has(obj);
We pass in a map and then check for its value with has
.
We can only pass objects into a WeakSet.
We’ll get a TypeError if we try to pass in a primitive value.
Also, we can use WeakSets to allow us to run a method on a given class instance.
For example, we can write:
const bars = new WeakSet();
class Bar {
constructor() {
bars.add(this);
}
method() {
if (!bars.has(this)) {
throw new TypeError('not a bar instance');
}
}
}
We add the Bar
instance to the bars
WeakSet in the constructor.
Then in the method
method, we check if the Bar
instance if part of the WeakSet with has
.
If it’s not, then we throw an error.
This prevents the method from being run on anything other than Bar
instances.
WeakSet API
WeakSets has a simple API with 3 methods and works like their Set
equivalents.
WeakSet.prototype.add
takes a value
as an argument and lets us add an entry to it.
WeakSet.prototype.has
takes a value
and returns true
if the entry exists and false
otherwise.
WeakSet.prototype.delete
takes a value
and removes the element from the WeakSet.
Conclusion
Sets let us add items without duplicating.
WeakSets let us hold items that can be garbage collected when they aren’t used.