ECMAScript® 2024 Language Specification

Draft ECMA-262 / February 15, 2024

24.1 Map Objects

Maps are collections of key/value pairs where both the keys and values may be arbitrary ECMAScript language values. A distinct key value may only occur in one key/value pair within the Map's collection. Distinct key values are discriminated using the SameValueZero comparison algorithm.

Maps 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 structure used in this specification is only intended to describe the required observable semantics of Maps. It is not intended to be a viable implementation model.

24.1.1 The Map Constructor

The Map constructor:

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

24.1.1.1 Map ( [ iterable ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let map be ? OrdinaryCreateFromConstructor(NewTarget, "%Map.prototype%", « [[MapData]] »).
  3. Set map.[[MapData]] to a new empty List.
  4. If iterable is either undefined or null, return map.
  5. Let adder be ? Get(map, "set").
  6. If IsCallable(adder) is false, throw a TypeError exception.
  7. Return ? AddEntriesFromIterable(map, iterable, adder).
Note

If the parameter iterable is present, it is expected to be an object that implements an @@iterator method that returns an iterator object that produces a two element array-like object whose first element is a value that will be used as a Map key and whose second element is the value to associate with that key.

24.1.1.2 AddEntriesFromIterable ( target, iterable, adder )

The abstract operation AddEntriesFromIterable takes arguments target (an Object), iterable (an ECMAScript language value, but not undefined or null), and adder (a function object) and returns either a normal completion containing an ECMAScript language value or a throw completion. adder will be invoked, with target as the receiver. It performs the following steps when called:

  1. Let iteratorRecord be ? GetIterator(iterable, sync).
  2. Repeat,
    1. Let next be ? IteratorStepValue(iteratorRecord).
    2. If next is done, return target.
    3. If next is not an Object, then
      1. Let error be ThrowCompletion(a newly created TypeError object).
      2. Return ? IteratorClose(iteratorRecord, error).
    4. Let k be Completion(Get(next, "0")).
    5. IfAbruptCloseIterator(k, iteratorRecord).
    6. Let v be Completion(Get(next, "1")).
    7. IfAbruptCloseIterator(v, iteratorRecord).
    8. Let status be Completion(Call(adder, target, « k, v »)).
    9. IfAbruptCloseIterator(status, iteratorRecord).
Note

The parameter iterable is expected to be an object that implements an @@iterator method that returns an iterator object that produces a two element array-like object whose first element is a value that will be used as a Map key and whose second element is the value to associate with that key.

24.1.2 Properties of the Map Constructor

The Map constructor:

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

24.1.2.1 Map.groupBy ( items, callbackfn )

Note

callbackfn should be a function that accepts two arguments. groupBy calls callbackfn once for each element in items, in ascending order, and constructs a new Map. Each value returned by callbackfn is used as a key in the Map. For each such key, the result Map has an entry whose key is that key and whose value is an array containing all the elements for which callbackfn returned that key.

callbackfn is called with two arguments: the value of the element and the index of the element.

The return value of groupBy is a Map.

This function performs the following steps when called:

  1. Let groups be ? GroupBy(items, callbackfn, zero).
  2. Let map be ! Construct(%Map%).
  3. For each Record { [[Key]], [[Elements]] } g of groups, do
    1. Let elements be CreateArrayFromList(g.[[Elements]]).
    2. Let entry be the Record { [[Key]]: g.[[Key]], [[Value]]: elements }.
    3. Append entry to map.[[MapData]].
  4. Return map.

24.1.2.2 Map.prototype

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

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

24.1.2.3 get Map [ @@species ]

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

  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.1.3 Properties of the Map Prototype Object

The Map prototype object:

24.1.3.1 Map.prototype.clear ( )

This method performs the following steps when called:

  1. Let M be the this value.
  2. Perform ? RequireInternalSlot(M, [[MapData]]).
  3. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
    1. Set p.[[Key]] to empty.
    2. Set p.[[Value]] to empty.
  4. Return undefined.
Note

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

24.1.3.2 Map.prototype.constructor

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

24.1.3.3 Map.prototype.delete ( key )

This method performs the following steps when called:

  1. Let M be the this value.
  2. Perform ? RequireInternalSlot(M, [[MapData]]).
  3. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
    1. If p.[[Key]] is not empty and SameValueZero(p.[[Key]], key) is true, then
      1. Set p.[[Key]] to empty.
      2. Set p.[[Value]] to empty.
      3. Return true.
  4. 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.1.3.4 Map.prototype.entries ( )

This method performs the following steps when called:

  1. Let M be the this value.
  2. Return ? CreateMapIterator(M, key+value).

24.1.3.5 Map.prototype.forEach ( callbackfn [ , thisArg ] )

This method performs the following steps when called:

  1. Let M be the this value.
  2. Perform ? RequireInternalSlot(M, [[MapData]]).
  3. If IsCallable(callbackfn) is false, throw a TypeError exception.
  4. Let entries be M.[[MapData]].
  5. Let numEntries be the number of elements in entries.
  6. Let index be 0.
  7. Repeat, while index < numEntries,
    1. Let e be entries[index].
    2. Set index to index + 1.
    3. If e.[[Key]] is not empty, then
      1. Perform ? Call(callbackfn, thisArg, « e.[[Value]], e.[[Key]], M »).
      2. NOTE: The number of elements in entries may have increased during execution of callbackfn.
      3. Set numEntries to the number of elements in entries.
  8. Return undefined.
Note

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

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 value of the item, the key of the item, and the Map being traversed.

forEach does not directly mutate the object on which it is called but the object may be mutated by the calls to callbackfn. Each entry of a map's [[MapData]] is only visited once. New keys added after the call to forEach begins are visited. A key will be revisited if it is deleted after it has been visited and then re-added before the forEach call completes. Keys that are deleted after the call to forEach begins and before being visited are not visited unless the key is added again before the forEach call completes.

24.1.3.6 Map.prototype.get ( key )

This method performs the following steps when called:

  1. Let M be the this value.
  2. Perform ? RequireInternalSlot(M, [[MapData]]).
  3. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
    1. If p.[[Key]] is not empty and SameValueZero(p.[[Key]], key) is true, return p.[[Value]].
  4. Return undefined.

24.1.3.7 Map.prototype.has ( key )

This method performs the following steps when called:

  1. Let M be the this value.
  2. Perform ? RequireInternalSlot(M, [[MapData]]).
  3. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
    1. If p.[[Key]] is not empty and SameValueZero(p.[[Key]], key) is true, return true.
  4. Return false.

24.1.3.8 Map.prototype.keys ( )

This method performs the following steps when called:

  1. Let M be the this value.
  2. Return ? CreateMapIterator(M, key).

24.1.3.9 Map.prototype.set ( key, value )

This method performs the following steps when called:

  1. Let M be the this value.
  2. Perform ? RequireInternalSlot(M, [[MapData]]).
  3. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
    1. If p.[[Key]] is not empty and SameValueZero(p.[[Key]], key) is true, then
      1. Set p.[[Value]] to value.
      2. Return M.
  4. If key is -0𝔽, set key to +0𝔽.
  5. Let p be the Record { [[Key]]: key, [[Value]]: value }.
  6. Append p to M.[[MapData]].
  7. Return M.

24.1.3.10 get Map.prototype.size

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

  1. Let M be the this value.
  2. Perform ? RequireInternalSlot(M, [[MapData]]).
  3. Let count be 0.
  4. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
    1. If p.[[Key]] is not empty, set count to count + 1.
  5. Return 𝔽(count).

24.1.3.11 Map.prototype.values ( )

This method performs the following steps when called:

  1. Let M be the this value.
  2. Return ? CreateMapIterator(M, value).

24.1.3.12 Map.prototype [ @@iterator ] ( )

The initial value of the @@iterator property is %Map.prototype.entries%, defined in 24.1.3.4.

24.1.3.13 Map.prototype [ @@toStringTag ]

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

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

24.1.4 Properties of Map Instances

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

24.1.5 Map Iterator Objects

A Map Iterator is an object, that represents a specific iteration over some specific Map instance object. There is not a named constructor for Map Iterator objects. Instead, map iterator objects are created by calling certain methods of Map instance objects.

24.1.5.1 CreateMapIterator ( map, kind )

The abstract operation CreateMapIterator takes arguments map (an ECMAScript language value) and kind (key+value, key, or value) and returns either a normal completion containing a Generator or a throw completion. It is used to create iterator objects for Map methods that return such iterators. It performs the following steps when called:

  1. Perform ? RequireInternalSlot(map, [[MapData]]).
  2. Let closure be a new Abstract Closure with no parameters that captures map and kind and performs the following steps when called:
    1. Let entries be map.[[MapData]].
    2. Let index be 0.
    3. Let numEntries be the number of elements in entries.
    4. Repeat, while index < numEntries,
      1. Let e be entries[index].
      2. Set index to index + 1.
      3. If e.[[Key]] is not empty, then
        1. If kind is key, then
          1. Let result be e.[[Key]].
        2. Else if kind is value, then
          1. Let result be e.[[Value]].
        3. Else,
          1. Assert: kind is key+value.
          2. Let result be CreateArrayFromListe.[[Key]], e.[[Value]] »).
        4. Perform ? GeneratorYield(CreateIterResultObject(result, false)).
        5. NOTE: The number of elements in entries may have increased while execution of this abstract operation was paused by Yield.
        6. Set numEntries to the number of elements in entries.
    5. Return undefined.
  3. Return CreateIteratorFromClosure(closure, "%MapIteratorPrototype%", %MapIteratorPrototype%).

24.1.5.2 The %MapIteratorPrototype% Object

The %MapIteratorPrototype% object:

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

24.1.5.2.1 %MapIteratorPrototype%.next ( )

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

24.1.5.2.2 %MapIteratorPrototype% [ @@toStringTag ]

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

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