Карты (Map) — это наборы пар ключ/значение, где как ключи, так и значения могут быть произвольными значениями языка ECMAScript. Отдельное значение ключа может встречаться только в одной паре ключ/значение в коллекции Карты (Map). Различные ключевые значения различаются с помощью алгоритма сравнения SameValueZero.
Карты должны быть реализованы с использованием либо хэш-таблиц, либо других механизмов, которые в среднем обеспечивают время доступа, сублинейно зависящее от количества элементов в коллекции. Структура данных, используемая в этой спецификации, предназначена только для описания требуемой наблюдаемой семантики Карт (Map). Он не предназначен для использования в качестве жизнеспособной модели реализации.
24.1.1 Конструктор Карты (Map Constructor)
Конструктор Карты (Map):
- является %Map%.
- является начальным значением свойства «Map» для глобального объекта.
- создает и инициализирует новую Карту (Map) при вызове в качестве конструктора.
- не предназначен для вызова как функция и вызовет исключение при таком вызове.
- может использоваться как значение в предложении
extends
определения класса. Конструкторы подкласса, которые намереваются наследовать указанное поведение Map, должны включать супервызовsuper
конструктора Карты (Map) для создания и инициализации экземпляра подкласса с внутренним состоянием, необходимым для поддержки встроенных методовMap.prototype
.
24.1.1.1 Map ( [ iterable ] )
Когда функция Map вызывается с необязательным аргументом iterable, выполняются следующие шаги:
1. Если NewTarget является undefined (не определен), выбросить исключение TypeError. 2. Пусть map будет ? OrdinaryCreateFromConstructor(NewTarget, "%Map.prototype%", «[[MapData]]»). 3. Установите map.[[MapData]] в новый пустой Список. 4. Если iterable является undefined (не определен) или null, вернуть map. 5. Пусть adder будет ? Получить Get(map, "set"). 6. Вернуть ? AddEntriesFromIterable(map, iterable, adder).
Если параметр iterable присутствует, ожидается, что это будет объект, реализующий метод @@iterator, который возвращает объект-итератор, который создает двухэлементный объект, подобный массиву, первый элемент которого является значением, которое будет использоваться в качестве ключа Карты (Map) и второй элемент которого — значение, которое нужно связать с этим ключом.
24.1.1.2 AddEntriesFromIterable ( target, iterable, adder )
Абстрактная операция AddEntriesFromIterable принимает аргументы target, iterable (значение языка ECMAScript, но не undefined или null) и adder (объект функции). adder будет вызван с target в качестве получателя. При вызове она выполняет следующие шаги:
1. Если IsCallable(adder) имеет значение false, выбросить исключение TypeError. 2. Пусть iteratorRecord будет ? GetIterator(iterable). 3. Повторите, а. Пусть next будет ? IteratorStep(iteratorRecord). b. Если next является false, вернуть target. c. Пусть nextItem будет ? IteratorValue(next). d. Если Type(nextItem) не Object, то i. Пусть error будет ThrowCompletion(вновь созданный объект TypeError). ii. Вернуть ? IteratorClose(iteratorRecord, error). e. Пусть k будет Get(nextItem, "0"). f. IfAbruptCloseIterator(k, iteratorRecord). g. Пусть v будет Get(nextItem, "1"). h. IfAbruptCloseIterator(v, iteratorRecord). i. Пусть status будет Call(adder, target, «k, v»). j. IfAbruptCloseIterator(status, iteratorRecord).
Ожидается, что параметр iterable будет объектом, который реализует метод @@iterator, который возвращает объект-итератор, который создает двухэлементный объект, подобный массиву, первый элемент которого представляет собой значение, которое будет использоваться в качестве ключа карты, а второй элемент — значение, которое нужно связать с этим ключом.
24.1.2 Свойства конструктора Карты (Properties of the Map Constructor)
Конструктор Карты (Map constructor):
- имеет внутренний слот [[Prototype]], значение которого — %Function.prototype%.
- обладает следующими свойствами:
24.1.2.1 Map.prototype
Начальным значением Map.prototype
является объект-прототип Карты (Map).
Это свойство имеет атрибуты {[[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false}.
24.1.2.2 get Map [ @@species ]
Map[@@species]
— это свойство доступа, для которого функция доступа set является undefined (не определена). Его функция доступа get выполняет следующие шаги:
1. Верните значение this.
Значение свойства «name» этой функции является «get [Symbol.species]».
Методы, которые создают производные объекты коллекции, должны вызывать @@species, чтобы определить конструктор, который будет использоваться для создания производных объектов. Конструктор подкласса может переопределять @@species, чтобы изменить назначение конструктора по умолчанию.
24.1.3 Свойства объекта прототипа Карты (Properties of the Map Prototype Object)
Объект-прототип Карты (Map prototype object):
- это %Map.prototype%.
- имеет внутренний слот [[Prototype]], значение которого %Object.prototype%.
- это обычный объект.
- не имеет внутреннего слота [[MapData]].
24.1.3.1 Map.prototype.clear ( )
Выполняются следующие шаги:
1. Пусть M будет значением this. 2. Выполнить? RequireInternalSlot(M, [[MapData]]). 3. Пусть entries будет Список M.[[MapData]]. 4. Для каждой Записи {[[Key]], [[Value]]} p из entries выполните а. Установите p.[[Key]] на empty. b. Установите p.[[Value]] на empty. 5. Вернуть undefined.
Существующий Список [[MapData]] сохраняется, поскольку могут существовать объекты Map Iterator, которые приостанавливаются на полпути во время итерации по этому Списку.
24.1.3.2 Map.prototype.constructor
Начальное значение Map.prototype.constructor
является %Map%.
24.1.3.3 Map.prototype.delete ( key )
Выполняются следующие шаги:
1. Пусть M будет значением this. 2. Выполнить ? RequireInternalSlot(M, [[MapData]]). 3. Пусть entries будет список M.[[MapData]]. 4. Для каждой Записи {[[Key]], [[Value]]} p из entries выполните а. Если p.[[Key]] не empty и SameValueZero(p.[[Key]], key) является true, то i. Установите p.[[Key]] на empty. ii. Установите p.[[Value]] на empty. iii. Верните true. 5. Вернуть false.
Пустое значение empty используется как устройство спецификации, чтобы указать, что запись была удалена. Фактические реализации могут выполнять другие действия, такие как физическое удаление записи из внутренних структур данных.
24.1.3.4 Map.prototype.entries ( )
Выполняются следующие шаги:
1. Пусть M будет значением this. 2. Вернуть ? CreateMapIterator(M, key+value).
24.1.3.5 Map.prototype.forEach ( callbackfn [ , thisArg ] )
Когда метод forEach вызывается с одним или двумя аргументами, выполняются следующие шаги:
1. Пусть M будет значением this. 2. Выполнить ? RequireInternalSlot(M, [[MapData]]). 3. Если IsCallable(callbackfn) является false, выбросить исключение TypeError. 4. Пусть записями entries будет Список M.[[MapData]]. 5. Для каждой Записи {[[Key]], [[Value]]} e из entries выполните а. Если e.[[Key]] не является empty, то i. Выполнить ? Вызов Call(callbackfn, thisArg, « e.[[Value]], e.[[Key]], M »). 6. Вернуть undefined.
callbackfn должен быть функцией, которая принимает три аргумента. forEach вызывает callbackfn один раз для каждой пары ключ/значение, присутствующей в Карте (Map), в порядке вставки ключей. callbackfn вызывается только для реально существующих ключей Карты (Map); он не вызывается для ключей, которые были удалены с Карты (Map).
Если указан параметр thisArg, он будет использоваться как значение this для каждого вызова callbackfn. Если он не указан, вместо него используется undefined.
callbackfn вызывается с тремя аргументами:
- значением элемента
- ключом элемента
- просматриваемой Картой (Map)
forEach не изменяет напрямую объект, для которого он вызывается, но объект может быть изменен вызовами callbackfn. Каждая запись [[MapData]] карты просматривается только один раз. Посещаются новые ключи, добавленные после начала вызова forEach. Ключ будет повторно посещен, если он будет удален после посещения, а затем повторно добавлен до завершения вызова forEach. Ключи, которые удаляются после начала вызова forEach и до посещения, не посещаются, если ключ не добавлен снова до завершения вызова forEach.
24.1.3.6 Map.prototype.get ( key )
Выполняются следующие шаги:
1. Пусть M будет значением this. 2. Выполнить ? RequireInternalSlot(M, [[MapData]]). 3. Пусть записями entries будет Список M.[[MapData]]. 4. Для каждой Записи {[[Key]], [[Value]]} p из entries выполните а. Если p.[[Key]] не является empty и SameValueZero(p.[[Key]], key) является true, вернуть p.[[Value]]. 5. Вернуть undefined.
24.1.3.7 Map.prototype.has ( key )
Выполняются следующие шаги:
1. Пусть M будет значением this. 2. Выполнить ? RequireInternalSlot(M, [[MapData]]). 3. Пусть записями entries будет Список, который является M.[[MapData]]. 4. Для каждой Записи {[[Key]], [[Value]]} p из записей entries выполните а. Если p.[[Key]] не является empty и SameValueZero(p.[[Key]], key) является true, верните true. 5. Вернуть false.
24.1.3.8 Map.prototype.keys ( )
Выполняются следующие шаги:
1. Пусть M будет значением this. 2. Вернуть ? CreateMapIterator(M, key).
24.1.3.9 Map.prototype.set ( key, value )
Выполняются следующие шаги:
1. Пусть M будет значением this. 2. Выполнить ? RequireInternalSlot(M, [[MapData]]). 3. Пусть записями entries будет Список, который является M.[[MapData]]. 4. Для каждой Записи {[[Key]], [[Value]]} p из записей entries выполните а. Если p.[[Key]] не является empty и SameValueZero(p.[[Key]], key) является true, то i. Установите p.[[Value]] на value. ii. Вернуть M. 5. Если key равен -0𝔽, установите key на +0𝔽. 6. Пусть p будет Записью {[[Key]]: key, [[Value]]: value}. 7. Добавьте p в качестве последнего элемента entries. 8. Верните M.
24.1.3.10 get Map.prototype.size
Map.prototype.size — это свойство доступа, для которого функция доступа set является undefined (не определена). Его функция доступа get выполняет следующие шаги:
1. Пусть M будет значением this. 2. Выполнить ? RequireInternalSlot(M, [[MapData]]). 3. Пусть записями entries будет Список M.[[MapData]]. 4. Пусть count будет 0. 5. Для каждой Записи {[[Key]], [[Value]]} p из записей entries выполните а. Если p.[[Key]] не является empty, установите count на count + 1. 6. Верните 𝔽(count).
24.1.3.11 Map.prototype.values ( )
Выполняются следующие шаги:
1. Пусть M будет значением this. 2. Вернуть ? CreateMapIterator(M, value).
24.1.3.12 Map.prototype [ @@iterator ] ( )
Начальным значением свойства @@iterator является тот же функциональный объект, что и начальное значение свойства «entries».
24.1.3.13 Map.prototype [ @@toStringTag ]
Начальным значением свойства @@toStringTag является строковое значение «Map».
Это свойство имеет атрибуты {[[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}.
24.1.4 Свойства экземпляров Карты (Properties of Map Instances)
Экземпляры Карты (Map instances) — это обычные объекты, наследующие свойства от прототипа Карты (Map prototype). Экземпляры Карт также имеют внутренний слот [[MapData]].
24.1.5 Объекты Итераторы Карты (Map Iterator Objects)
Итератор Карты (Map Iterator) — это объект, который представляет определенную итерацию над некоторым конкретным объектом экземпляра Карты. Для объектов Итератора Карты (Map Iterator) не существует именованного конструктора. Вместо этого объекты Итератора Карты создаются путем вызова определенных методов объектов Экземпляра Карты.
24.1.5.1 CreateMapIterator ( map, kind )
Абстрактная операция CreateMapIterator принимает аргумент map (значение языка ECMAScript) и тип kind (key+value, key или value). Он используется для создания объектов итераторов для методов Карты (Map), которые возвращают такие итераторы. При вызове он выполняет следующие шаги:
1. Выполнить ? RequireInternalSlot(map, [[MapData]]). 2. Пусть замыкание closure будет новым Абстрактным Замыканием без параметров, которое захватывает map и kind и при вызове выполняет следующие шаги: а. Пусть записями entries будет Список, который является map.[[MapData]]. b. Пусть index равен 0. c. Пусть numEntries будет количеством элементов записей entries. d. Повторите, пока index < numEntries, i. Пусть e будет Записью {[[Key]], [[Value]]}, которая является значением entries[index]. ii. Установите index на index + 1. iii. Если e.[[Key]] не является empty, то 1. Если kind является key, пусть result будет e.[[Key]]. 2. Иначе, если kind является value, пусть result будет e.[[Value]]. 3. Иначе, а. Утверждено: kind - это key+value. b. Пусть result будет ! CreateArrayFromList(« e.[[Ключ]], e.[[Значение]] »). 4. Выполнить ? Урожайность Yield(result). 5. ПРИМЕЧАНИЕ. Количество элементов в записях entries могло измениться, пока выполнение этой абстрактной операции было приостановлено Yield. 6. Установите numEntries равным количеству элементов записей entries. e. Вернуть undefined. 3. Вернуть ! CreateIteratorFromClosure(closure, "%MapIteratorPrototype%", %MapIteratorPrototype%).
24.1.5.2 Объект %MapIteratorPrototype%
Объект %MapIteratorPrototype%:
- имеет свойства, которые наследуются всеми объектами Итератора Карты (Map Iterator).
- это обычный объект.
- имеет внутренний слот [[Prototype]], значение которого %IteratorPrototype%.
- обладает следующими свойствами:
24.1.5.2.1 %MapIteratorPrototype%.next ( )
1. Вернуть ? GeneratorResume(значение this, empty, "%MapIteratorPrototype%").
24.1.5.2.2 %MapIteratorPrototype% [ @@toStringTag ]
Начальным значением свойства @@toStringTag является строковое значение «Map Iterator».
Это свойство имеет атрибуты {[[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}.
Информационные ссылки
Стандарт ECMAScript — Раздел «24.1 Map Objects» — https://tc39.es/ecma262/#sec-map-objects