24.2 Set Objects

Set objects are collections of ECMAScript language values. A distinct value may only occur once as an element of a Set's collection. Distinct values are discriminated using the SameValueZero comparison algorithm.

Set objects must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements in the collection. The data structures used in this Set objects specification is only intended to describe the required observable semantics of Set objects. It is not intended to be a viable implementation model.

24.2.1 The Set Constructor

The Set constructor:

  • is %Set%.
  • is the initial value of the "Set" property of the global object.
  • creates and initializes a new Set object when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • is designed to be subclassable. It may be used as the value in an extends clause of a class definition. Subclass constructors that intend to inherit the specified Set behaviour must include a super call to the Set constructor to create and initialize the subclass instance with the internal state necessary to support the Set.prototype built-in methods.

24.2.1.1 Set ( [ iterable ] )

When the Set function is called with optional argument iterable, the following steps are taken:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let set be ? OrdinaryCreateFromConstructor(NewTarget, "%Set.prototype%", « [[SetData]] »).
  3. Set set.[[SetData]] to a new empty List.
  4. If iterable is either undefined or null, return set.
  5. Let adder be ? Get(set, "add").
  6. If IsCallable(adder) is false, throw a TypeError exception.
  7. Let iteratorRecord be ? GetIterator(iterable).
  8. Repeat,
    1. Let next be ? IteratorStep(iteratorRecord).
    2. If next is false, return set.
    3. Let nextValue be ? IteratorValue(next).
    4. Let status be Call(adder, set, « nextValue »).
    5. If status is an abrupt completion, return ? IteratorClose(iteratorRecord, status).

24.2.2 Properties of the Set Constructor

The Set constructor:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • has the following properties:

24.2.2.1 Set.prototype

The initial value of Set.prototype is the Set prototype object.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

24.2.2.2 get Set [ @@species ]

Set[@@species] is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Return the this value.

The value of the "name" property of this function is "get [Symbol.species]".

Note

Methods that create derived collection objects should call @@species to determine the constructor to use to create the derived objects. Subclass constructor may over-ride @@species to change the default constructor assignment.

24.2.3 Properties of the Set Prototype Object

The Set prototype object:

24.2.3.1 Set.prototype.add ( value )

The following steps are taken:

  1. Let S be the this value.
  2. Perform ? RequireInternalSlot(S, [[SetData]]).
  3. Let entries be the List that is S.[[SetData]].
  4. For each element e of entries, do
    1. If e is not empty and SameValueZero(e, value) is true, then
      1. Return S.
  5. If value is -0𝔽, set value to +0𝔽.
  6. Append value as the last element of entries.
  7. Return S.

24.2.3.2 Set.prototype.clear ( )

The following steps are taken:

  1. Let S be the this value.
  2. Perform ? RequireInternalSlot(S, [[SetData]]).
  3. Let entries be the List that is S.[[SetData]].
  4. For each element e of entries, do
    1. Replace the element of entries whose value is e with an element whose value is empty.
  5. Return undefined.
Note

The existing [[SetData]] List is preserved because there may be existing Set Iterator objects that are suspended midway through iterating over that List.

24.2.3.3 Set.prototype.constructor

The initial value of Set.prototype.constructor is %Set%.

24.2.3.4 Set.prototype.delete ( value )

The following steps are taken:

  1. Let S be the this value.
  2. Perform ? RequireInternalSlot(S, [[SetData]]).
  3. Let entries be the List that is S.[[SetData]].
  4. For each element e of entries, do
    1. If e is not empty and SameValueZero(e, value) is true, then
      1. Replace the element of entries whose value is e with an element whose value is empty.
      2. Return true.
  5. Return false.
Note

The value empty is used as a specification device to indicate that an entry has been deleted. Actual implementations may take other actions such as physically removing the entry from internal data structures.

24.2.3.5 Set.prototype.entries ( )

The following steps are taken:

  1. Let S be the this value.
  2. Return ? CreateSetIterator(S, key+value).
Note

For iteration purposes, a Set appears similar to a Map where each entry has the same value for its key and value.

24.2.3.6 Set.prototype.forEach ( callbackfn [ , thisArg ] )

When the forEach method is called with one or two arguments, the following steps are taken:

  1. Let S be the this value.
  2. Perform ? RequireInternalSlot(S, [[SetData]]).
  3. If IsCallable(callbackfn) is false, throw a TypeError exception.
  4. Let entries be the List that is S.[[SetData]].
  5. For each element e of entries, do
    1. If e is not empty, then
      1. Perform ? Call(callbackfn, thisArg, « e, e, S »).
  6. Return undefined.
Note

callbackfn should be a function that accepts three arguments. forEach calls callbackfn once for each value present in the set object, in value insertion order. callbackfn is called only for values of the Set which actually exist; it is not called for keys that have been deleted from the set.

If a thisArg parameter is provided, it will be used as the this value for each invocation of callbackfn. If it is not provided, undefined is used instead.

callbackfn is called with three arguments: the first two arguments are a value contained in the Set. The same value is passed for both arguments. The Set object being traversed is passed as the third argument.

The callbackfn is called with three arguments to be consistent with the call back functions used by forEach methods for Map and Array. For Sets, each item value is considered to be both the key and the value.

forEach does not directly mutate the object on which it is called but the object may be mutated by the calls to callbackfn.

Each value is normally visited only once. However, a value will be revisited if it is deleted after it has been visited and then re-added before the forEach call completes. Values that are deleted after the call to forEach begins and before being visited are not visited unless the value is added again before the forEach call completes. New values added after the call to forEach begins are visited.

24.2.3.7 Set.prototype.has ( value )

The following steps are taken:

  1. Let S be the this value.
  2. Perform ? RequireInternalSlot(S, [[SetData]]).
  3. Let entries be the List that is S.[[SetData]].
  4. For each element e of entries, do
    1. If e is not empty and SameValueZero(e, value) is true, return true.
  5. Return false.

24.2.3.8 Set.prototype.keys ( )

The initial value of the "keys" property is the same function object as the initial value of the "values" property.

Note

For iteration purposes, a Set appears similar to a Map where each entry has the same value for its key and value.

24.2.3.9 get Set.prototype.size

Set.prototype.size is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let S be the this value.
  2. Perform ? RequireInternalSlot(S, [[SetData]]).
  3. Let entries be the List that is S.[[SetData]].
  4. Let count be 0.
  5. For each element e of entries, do
    1. If e is not empty, set count to count + 1.
  6. Return 𝔽(count).

24.2.3.10 Set.prototype.values ( )

The following steps are taken:

  1. Let S be the this value.
  2. Return ? CreateSetIterator(S, value).

24.2.3.11 Set.prototype [ @@iterator ] ( )

The initial value of the @@iterator property is the same function object as the initial value of the "values" property.

24.2.3.12 Set.prototype [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Set".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

24.2.4 Properties of Set Instances

Set instances are ordinary objects that inherit properties from the Set prototype. Set instances also have a [[SetData]] internal slot.

24.2.5 Set Iterator Objects

A Set Iterator is an ordinary object, with the structure defined below, that represents a specific iteration over some specific Set instance object. There is not a named constructor for Set Iterator objects. Instead, set iterator objects are created by calling certain methods of Set instance objects.

24.2.5.1 CreateSetIterator ( set, kind )

The abstract operation CreateSetIterator takes arguments set and kind. This operation is used to create iterator objects for Set methods that return such iterators. It performs the following steps when called:

  1. Assert: kind is key+value or value.
  2. Perform ? RequireInternalSlot(set, [[SetData]]).
  3. Let closure be a new Abstract Closure with no parameters that captures set and kind and performs the following steps when called:
    1. Let index be 0.
    2. Let entries be the List that is set.[[SetData]].
    3. Let numEntries be the number of elements of entries.
    4. Repeat, while index < numEntries,
      1. Let e be entries[index].
      2. Set index to index + 1.
      3. If e is not empty, then
        1. If kind is key+value, then
          1. Perform ? Yield(! CreateArrayFromListe, e »)).
        2. Else,
          1. Assert: kind is value.
          2. Perform ? Yield(e).
        3. NOTE: the number of elements in entries may have changed while execution of this abstract operation was paused by Yield.
        4. Set numEntries to the number of elements of entries.
    5. Return undefined.
  4. Return ! CreateIteratorFromClosure(closure, "%SetIteratorPrototype%", %SetIteratorPrototype%).

24.2.5.2 The %SetIteratorPrototype% Object

The %SetIteratorPrototype% object:

  • has properties that are inherited by all Set Iterator Objects.
  • is an ordinary object.
  • has a [[Prototype]] internal slot whose value is %IteratorPrototype%.
  • has the following properties:

24.2.5.2.1 %SetIteratorPrototype%.next ( )

  1. Return ? GeneratorResume(this value, empty, "%SetIteratorPrototype%").

24.2.5.2.2 %SetIteratorPrototype% [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Set Iterator".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.