ECMAScript | Объекты Наборы (Set Objects)

ECMAScript | Объекты Наборы (Set Objects)

Объекты Set (Набор) — это коллекции значений языка ECMAScript. Отдельное значение может встречаться только один раз как элемент коллекции Set. Различающиеся значения различаются с помощью алгоритма сравнения SameValueZero.

Объекты набора должны быть реализованы с использованием либо хэш-таблиц, либо других механизмов, которые в среднем обеспечивают время доступа, сублинейно зависящее от количества элементов в коллекции. Структуры данных, используемые в этой спецификации объектов Set, предназначены только для описания требуемой наблюдаемой семантики объектов Set. Он не предназначен для использования в качестве жизнеспособной модели реализации.

 

24.2.1 Конструктор Набора (Set Constructor)

Конструктор Набора (Set):

  • является %Set%.
  • это начальное значение свойства «Set» для глобального объекта.
  • создает и инициализирует новый объект Set при вызове в качестве конструктора.
  • не предназначен для вызова как функция и вызовет исключение при таком вызове.
  • предназначен для создания подклассов. Он может использоваться как значение в предложении extends определения класса. Конструкторы подклассов, которые намереваются унаследовать указанное поведение Set, должны включать супервызов super конструктора Set для создания и инициализации экземпляра подкласса с внутренним состоянием, необходимым для поддержки встроенных методов Set.prototype.

 

24.2.1.1 Set ( [ iterable ] )

Когда функция Set вызывается с необязательным аргументом итерации iterable, выполняются следующие шаги:

1. Если NewTarget не определен (является undefined), выбросить исключение TypeError.
2. Пусть set будет ? OrdinaryCreateFromConstructor(NewTarget, "%Set.prototype%", « [[SetData]] »).
3. Установите set.[[SetData]] в новый пустой Список.
4. Если iterable не определена или равна нулю, вернуть set.
5. Пусть adder будет ? Get(set, "add").
6. Если IsCallable(adder) имеет значение false, выбросить исключение TypeError.
7. Пусть iteratorRecord будет ? GetIterator(iterable).
8. Повторять,
   a. Пусть next будет ? IteratorStep(iteratorRecord).
   b. Если next ложно false, вернуть set.
   c. Пусть nextValue будет ? IteratorValue(next).
   d. Пусть status будет Call(adder, set, « nextValue »).
   e. Если status - внезапное завершение, вернуть ? IteratorClose(iteratorRecord, status).

 

24.2.2 Свойства Конструктора Набора (Properties of the Set Constructor)

Конструктор Набора (Set):

  • имеет внутренний слот [[Prototype]], значение которого — %Function.prototype%.
  • обладает следующими свойствами:

 

24.2.2.1 Set.prototype

Начальным значением Set.prototype является объект прототипа Set.

Это свойство имеет атрибуты {[[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false}.

 

24.2.2.2 get Set [ @@species ]

Set[@@species] — это свойство доступа, функция доступа которого не определена (является undefined). Его функция доступа get выполняет следующие шаги:

1. Вернуть значение this.

Значение свойства «name» этой функции — «get [Symbol.species]».

Примечание

Методы, которые создают производные объекты коллекции, должны вызывать разновидности @@species, чтобы определить конструктор, который будет использоваться для создания производных объектов. Подкласс конструктора может переопределить разновидности @@species, чтобы изменить назначение конструктора по умолчанию.

 

24.2.3 Свойства объекта прототипа Набора (Properties of the Set Prototype Object)

Объект прототипа набора — Set prototype object:

  • является %Set.prototype%.
  • имеет внутренний слот [[Prototype]], значение которого равно %Object.prototype%.
  • является обычным объектом.
  • не имеет внутреннего слота [[SetData]].

 

24.2.3.1 Set.prototype.add ( value )

Выполняются следующие шаги:

1. Пусть S будет значением this.
2. Выполнить ? RequireInternalSlot(S, [[SetData]]).
3. Пусть записями entries будет список S.[[SetData]].
4. Для каждого элемента e из записей entries выполните
   a. Если e не является empty и SameValueZero(e, value) истинно, то
      i. Вернуть S
5. Если значение value равно -0𝔽, установите значение value на +0𝔽.
6. Добавить значение value в качестве последнего элемента записей entries.
7. Вернуть S

 

24.2.3.2 Set.prototype.clear ( )

Выполняются следующие шаги:

1. Пусть S будет значением this.
2. Выполнить ? RequireInternalSlot(S, [[SetData]]).
3. Пусть записями entries будет список S.[[SetData]].
4. Для каждого элемента e из записей entries выполните
   a. Замените элемент записей entries, значение которых равно e, на элемент, значение которого является empty.
5. Вернуть undefined
Примечание

Существующий Список [[SetData]] сохраняется, поскольку могут существовать объекты Set Iterator, которые приостанавливаются на полпути во время итерации по этому Списку.

 

24.2.3.3 Set.prototype.constructor

Начальное значение Set.prototype.constructor — это %Set%.

 

24.2.3.4 Set.prototype.delete ( value )

Выполняются следующие шаги:

1. Пусть S будет значением this.
2. Выполнить ? RequireInternalSlot(S, [[SetData]]).
3. Пусть записями entries будет список S.[[SetData]].
4. Для каждого элемента e из записей entries выполните
   a. Если e не empty и SameValueZero(e, value) истинно true, то
      i. Замените элемент записей entries, значение которых равно e, на элемент, значение которого является empty.
      ii. Вернуть true
5. Вернуть false
Примечание

Значение empty используется в качестве устройства спецификации, чтобы указать, что запись была удалена. Фактические реализации могут выполнять другие действия, такие как физическое удаление записи из внутренних структур данных.

 

24.2.3.5 Set.prototype.entries ( )

Выполняются следующие шаги:

1. Пусть S будет значением this.
2. Вернуть ? CreateSetIterator(S, key+value).
Примечание

В целях итерации Set похож на Map, где каждая запись имеет одинаковое значение для своего ключа и значения.

 

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

Когда метод forEach вызывается с одним или двумя аргументами, выполняются следующие шаги:

1. Пусть S будет значением this.
2. Выполнить ? RequireInternalSlot(S, [[SetData]]).
3. Если IsCallable(callbackfn) имеет значение false, генерировать исключение TypeError.
4. Пусть записями entries будет список S.[[SetData]].
5. Для каждого элемента e из записей entries в исходном порядке вставки выполните
   a. Если e не empty, то
      i. Выполнить ? Call(callbackfn, thisArg, « e, e, S »).
6. Вернуть undefined
Примечание

callbackfn должен быть функцией, которая принимает три аргумента. forEach вызывает callbackfn один раз для каждого значения, присутствующего в заданном объекте, в порядке вставки значения. callbackfn вызывается только для значений набора Set, которые действительно существуют; он не вызывается для ключей, которые были удалены из набора.

Если указан параметр thisArg, он будет использоваться как значение this для каждого вызова callbackfn. Если он не указан, вместо него используется undefined.

callbackfn вызывается с тремя аргументами: первые два аргумента — это значение, содержащееся в наборе Set. Для обоих аргументов передается одно и то же значение. Обходимый объект Set передается в качестве третьего аргумента.

Функция callbackfn вызывается с тремя аргументами для согласования с функциями обратного вызова, используемыми методами forEach для Map и Array. Для наборов каждое значение элемента рассматривается как «ключ и значение».

forEach не изменяет напрямую объект, для которого он вызывается, но объект может быть изменен вызовами callbackfn.

Каждое значение обычно посещается только один раз. Однако значение будет пересмотрено, если оно будет удалено после посещения, а затем повторно добавлено до завершения вызова forEach. Значения, которые удаляются после начала вызова forEach и до посещения, не посещаются, если значение не добавлено снова до завершения вызова forEach. Посещаются новые значения, добавленные после начала вызова forEach.

 

24.2.3.7 Set.prototype.has ( value )

Выполняются следующие шаги:

1. Пусть S будет значением this.
2. Выполнить ? RequireInternalSlot(S, [[SetData]]).
3. Пусть записями entries будет список S.[[SetData]].
4. Для каждого элемента e из записей entries выполните
   a. Если e не empty и SameValueZero(e, value) истинно (является true), вернуть истину true.
5. Вернуть false

 

24.2.3.8 Set.prototype.keys ( )

Начальным значением свойства «keys» является тот же функциональный объект, что и начальное значение свойства «values».

Примечание

В целях итерации Set похож на Map, где каждая запись имеет одинаковое значение для своего ключа и значения.

 

24.2.3.9 get Set.prototype.size

Set.prototype.size — это свойство доступа, функция доступа которого не определена (является undefined). Его функция доступа get выполняет следующие шаги:

1. Пусть S будет значением this.
2. Выполнить ? RequireInternalSlot(S, [[SetData]]).
3. Пусть записями entries будет список S.[[SetData]].
4. Пусть count будет 0.
5. Для каждого элемента e из записей entries выполните
   a. Если e не empty, установите count на count + 1.
6. Вернуть count

 

24.2.3.10 Set.prototype.values ( )

Выполняются следующие шаги:

1. Пусть S будет значением this.
2. Вернуть ? CreateSetIterator(S, value).

 

24.2.3.11 Set.prototype [ @@iterator ] ( )

Начальным значением свойства @@iterator является тот же объект функции, что и начальное значение свойства «values».

 

24.2.3.12 Set.prototype [ @@toStringTag ]

Начальным значением свойства @@toStringTag является строковое значение «Set».

Это свойство имеет атрибуты {[[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}.

 

24.2.4 Свойства экземпляров Наборов (Properties of Set Instances)

Экземпляры Set — это обычные объекты, наследующие свойства от прототипа Set. У экземпляров Набора также есть внутренний слот [[SetData]].

 

24.2.5 Объекты Итератора Набора (Set Iterator Objects)

Итератор Набора (Set Iterator) — это обычный объект со структурой, определенной ниже, который представляет конкретную итерацию над некоторым конкретным объектом экземпляра набора Set. Для объектов Set Iterator не существует именованного конструктора. Вместо этого объекты Итератора Набора создаются путем вызова определенных методов объектов экземпляра набора.

24.2.5.1 CreateSetIterator ( set, kind )

Абстрактная операция CreateSetIterator принимает аргументы set (значение языка ECMAScript) и kind (key+value или value). Она используется для создания объектов-итераторов для методов Набора (Set), которые возвращают такие итераторы. При вызове она выполняет следующие шаги:

1. Выполнить ? RequireInternalSlot(set, [[SetData]]).
2. Пусть замыкание closure будет новым Абстрактным Замыканием без параметров, которое захватывают set и kind и при вызове выполняет следующие шаги:
  а. Пусть index равен 0.
  b. Пусть записями entries будет Список set.[[SetData]].
  c. Пусть numEntries будет количеством элементов записей entries.
  d. Повторите, пока index < numEntries,
    i. Пусть e будет entries[index].
    ii. Установите index на index + 1.
    iii. Если e не является empty, то
      1. Если kind является key+value, тогда
        а. Выполнить ? Yield(! CreateArrayFromListe, e »)).
      2. Иначе,
        а. Утверждено: kind является value.
        b. Выполнить ? Yield(e).
      3. ПРИМЕЧАНИЕ. Количество элементов в записях entries могло измениться, пока выполнение этой абстрактной операции было приостановлено Yield.
      4. Установите numEntries равным количеству элементов записей entries.
  e. Вернуть undefined.
3. Вернуть ! CreateIteratorFromClosure(closure, "%SetIteratorPrototype%", %SetIteratorPrototype%).

 


24.2.5.2 Объект %SetIteratorPrototype%

Объект %SetIteratorPrototype%:

  • имеет свойства, которые наследуются всеми объектами Итератора Набора (Set Iterator).
  • является обычным объектом
  • имеет внутренний слот [[Prototype]], значение которого %IteratorPrototype%.
  • обладает следующими свойствами:

 

24.2.5.2.1 %SetIteratorPrototype%.next ( )

Версия от сентября 2021 года:

1. Вернуть ? GeneratorResume(значение this, empty, "%SetIteratorPrototype%").

Версия от ноября 2020 года

1. Пусть O будет значением this.
2. Если Type(O) не является Объектом, вызовите исключение TypeError.
3. Если O не имеет всех внутренних слотов Экземпляра Set Iterator (23.2.5.3), выбросить исключение TypeError.
4. Пусть s будет O.[[IteratedSet]].
5. Пусть index будет O.[[SetNextIndex]].
6. Пусть itemKind будет O.[[SetIterationKind]].
7. Если s не определено, вернуть CreateIterResultObject(undefined, true).
8. Утверждение: s имеет внутренний слот [[SetData]].
9. Пусть записями entries будет Список, который является s.[[SetData]].
10. Пусть numEntries будет количеством элементов из записей entries.
11. ПРИМЕЧАНИЕ: numEntries необходимо переопределять каждый раз при оценке этого метода.
12. Повторите, пока index < numEntries,
   a. Пусть e будет entries[index].
   b. Установить index на index + 1.
   c. Установить O.[[SetNextIndex]] на index.
   d. Если e не empty, то
      i. Если itemKind является key+value (ключ + значение), тогда
         1. Вернуть CreateIterResultObject(CreateArrayFromListe, e »), false).
      ii. Утверждение: itemKind является value.
      iii. Верните CreateIterResultObject(e, false).
13. Установить O.[[IteratedSet]] на undefined.
14. Вернуть CreateIterResultObject(undefined, true).

 

24.2.5.2.2 %SetIteratorPrototype% [ @@toStringTag ]

Начальным значением свойства @@toStringTag является строковое значение «Set Iterator».

Это свойство имеет атрибуты {[[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}.

 

Свойства экземпляров итераторов набора (Properties of Set Iterator Instances)

Экземпляры Set Iterator — это обычные объекты, наследующие свойства от внутреннего объекта %SetIteratorPrototype%. Экземпляры Set Iterator изначально создаются с внутренними слотами, указанными в Таблице 65.

Внутренний слот (Internal Slot) Описание (Description)
[[IteratedSet]] Итерируемый объект Set.
[[SetNextIndex]] Целочисленный индекс следующего элемента [[SetData]], который будет проверяться этим итератором.
[[SetIterationKind]] Значение String, определяющее, что возвращается для каждого элемента итерации. Возможные значения: value и key+value.

 

Ссылки

ECMAScript — Официальная страница стандарта — Объекты Set — https://tc39.es/ecma262/#sec-set-objects