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 structure Set, 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:

    1. const set = new Set(['red', 'green', 'blue']);

    Third, the .add() method adds elements to a Set and is chainable:

    1. .add('red')
    2. .add('blue');

    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.

    1. const set = new Set();
    2. set.add('red');
    3. assert.equal(set.has('red'), false);

    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.

    1. const set = new Set()
    2. .add('bar')
    3. set.clear();

    32.1.4. Iterating over a set

    Sets are iterable and the for-of loop works as you’d expect:

    1. for (const x of set) {
    2. }
    3. // 'red'
    4. // 'blue'

    works with iterables and thus lets you convert a Set to an Array:

    1. const set = new Set(['red', 'green', 'blue']);
    32.1.4.1. Removing duplicates from Arrays and strings

    Converting an Array to a Set and back, removes duplicates from the Array:

    1. assert.deepEqual(
    2. [1, 2, 3]);

    Strings are also iterable and therefore can be used as parameters for new Set():

    1. [...new Set('ababccc')].join(''),

    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:

    1. > const set = new Set();
    2. > set.add('foo');
    3. 1
    4. > set.add('foo');

    Similarly to ===, two different objects are never considered equal (which can’t currently be customized):

    1. > const set = new Set();
    2. > set.add({});
    3. 1
    4. > set.add({});
    5. 2

    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

    1. const mappedSet = new Set([...set].map(x => x * 2));
    2. // Convert mappedSet to an Array to check what’s inside it

    32.3.2. Filtering

    1. const filteredSet = new Set([...set].filter(x => (x % 2) === 0));
    2. assert.deepEqual([...filteredSet], [2, 4]);

    32.3.3. Union

    Union (ab): create a Set that contains the elements of both Set a and Set b.

    1. const a = new Set([1,2,3]);
    2. // Use spreading to concatenate two iterables

    32.3.4. Intersection

    Intersection (ab): create a Set that contains those elements of Set a that are also in Set b.

    1. const b = new Set([4,3,2]);
    2. [...a].filter(x => b.has(x)));
    3. assert.deepEqual([...intersection], [2, 3]);

    32.3.5. Difference

    1. const a = new Set([1,2,3]);
    2. [...a].filter(x => !b.has(x)));
    3. assert.deepEqual([...difference], [1]);

    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:

    1. const set = new Set(['red', 'green', 'blue']);

    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.

    1. const set = new Set(['red', 'green', 'blue']);
    2. assert.deepEqual([...set], ['green', 'blue']);
    • .has(value: T): boolean [ES6]

    Checks whether value is in this Set.

    1. assert.equal(set.has('red'), true);

    32.4.3. Set<T>.prototype: all Set elements

    • get .size: number [ES6]

    Returns how many elements there are in this Set.

    1. assert.equal(set.size, 3);
    • .clear(): void [ES6]

    Removes all elements from this Set.

    1. assert.equal(set.size, 3);
    2. assert.equal(set.size, 0);

    32.4.4. Set<T>.prototype: iterating and looping

    • .values(): Iterable<T> [ES6]

    Returns an iterable over all elements of this Set.

    1. const set = new Set(['red', 'green']);
    2. console.log(x);
    3. // Output:
    4. // 'green'
    • : Iterable<T> [ES6]

    The default way of iterating over Sets. Same as .values().

    1. const set = new Set(['red', 'green']);
    2. console.log(x);
    3. // Output:
    4. // 'green'
    • .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.

    1. set.forEach(x => console.log(x));
    2. // 'red'

    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:
    1. const map = new Map(set.entries());
    2. [...map.entries()],