Before ES6, JavaScript didn’t have a data structure for sets. Instead, two work-around were used:
- The keys of objects as sets of strings.
- Arrays as sets of arbitrary values (e.g., checking if an element is in a set via ).
ECMAScript 6 has the data structureSet
, which works for arbitrary values.
32.1.1. Creating Sets
There are three common ways of creating Sets.
First, you can use the constructor without any parameters to create an empty Set:
Second, you can pass an iterable (e.g. an Array) to the constructor. The iterated values become elements of the new Set:
Third, the .add()
method adds elements to a Set and is chainable:
32.1.2. Adding, removing, checking inclusion
.add()
adds an element to a Set. .has()
checks if an element is included in a Set. .delete()
removes an element from a Set.
32.1.3. Determining the size of a Set and clearing it
.size
contains the number of elements in a Set. .clear()
removes all elements of a Set.
32.1.4. Iterating over a set
Sets are iterable and the for-of
loop works as you’d expect:
works with iterables and thus lets you convert a Set to an Array:
32.1.4.1. Removing duplicates from Arrays and strings
Converting an Array to a Set and back, removes duplicates from the Array:
Strings are also iterable and therefore can be used as parameters for new Set()
:
As with Maps, elements are compared similarly to ===
, with the exception of NaN
being equal to itself.
Adding an element a second time has no effect:
Similarly to ===
, two different objects are never considered equal (which can’t currently be customized):
Sets are missing several common operations. They can usually be implemented by:
- Converting Sets to Arrays (via ).
- Performing the operation.
- Converting the result back to a Set.
32.3.1. Mapping
32.3.2. Filtering
32.3.3. Union
Union (a
∪ b
): create a Set that contains the elements of both Set a
and Set b
.
32.3.4. Intersection
Intersection (a
∩ b
): create a Set that contains those elements of Set a
that are also in Set b
.
32.3.5. Difference
32.4.1. Constructor
new Set<T>(values?: Iterable<T>)
[ES6]
If you don’t provide the parameter values
then an empty Set is created. If you do then the iterated values are added as elements to the Set. For example:
32.4.2. Set<T>.prototype: single Set elements
.add(value: T): this
[ES6]
Adds value
to this Set. This method returns , which means that it can be chained.
.delete(value: T): boolean
[ES6]
Removes value
from this Set.
.has(value: T): boolean
[ES6]
Checks whether value
is in this Set.
32.4.3. Set<T>.prototype: all Set elements
get .size: number
[ES6]
Returns how many elements there are in this Set.
.clear(): void
[ES6]
Removes all elements from this Set.
32.4.4. Set<T>.prototype: iterating and looping
.values(): Iterable<T>
[ES6]
Returns an iterable over all elements of this Set.
: Iterable<T>
[ES6]
The default way of iterating over Sets. Same as .values()
.
.forEach(callback: (value: T, value2: T, theSet: Set<T>) => void, thisArg?: any): void
[ES6]
Loops over the elements of this Set and invokes the callback (first parameter) for each one. value
and key
are both set to the element, so that this method works similarly to Map.prototype.forEach
. If thisArg
is provided, this
is set to it for each call. Otherwise, this
is set to undefined
.
32.4.5. Symmetry with Map
Set.prototype.entries(): Iterable<[T,T]>
[ES6]Set.prototype.keys(): Iterable<T>
[ES6].entries()
enables you to convert a Set to a Map: