24 键控集合

24.1 Map 对象

Map 是键/值对的集合,其中键和值都可以是任意 ECMAScript 语言值。在 Map 的集合中,一个不同的键值只能出现在一个键/值对中。不同键值使用 SameValueZero 比较算法的语义加以区分。

Map 必须使用哈希表或其他机制来实现,这些机制平均而言能提供相对于集合中元素数量为次线性的访问时间。本规范中使用的数据结构仅用于描述 Map 所要求的可观察语义。它并不意图作为可行的实现模型。

24.1.1 Map 构造器

Map 构造器

  • %Map%
  • 全局对象"Map" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 Map。
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 Map 行为的子类构造器必须包含对 Map 构造器super 调用,以创建并初始化带有支持 Map.prototype 内置方法所需内部状态的子类实例。

24.1.1.1 Map ( [ iterable ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. map 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Map.prototype%", « [[MapData]] »)。
  3. map.[[MapData]] 设置为一个新的空 List
  4. 如果 iterableundefinednull,返回 map
  5. adder 为 ? Get(map, "set")。
  6. 如果 IsCallable(adder) 是 false,抛出 TypeError 异常。
  7. 返回 ? AddEntriesFromIterable(map, iterable, adder)。
Note

如果存在参数 iterable,则期望它是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个迭代器对象,产生一个双元素类数组对象,其第一个元素是将用作 Map 键的值,第二个元素是要与该键关联的值。

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 Object or a throw completion. adder 将以 target 作为接收者被调用。 It performs the following steps when called:

  1. iteratorRecord 为 ? GetIterator(iterable, sync)。
  2. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 target
    3. 如果 next 不是 Object,则
      1. errorThrowCompletion(一个新创建的 TypeError 对象)。
      2. 返回 ? IteratorClose(iteratorRecord, error)。
    4. keyCompletion(Get(next, "0"))。
    5. IfAbruptCloseIterator(key, iteratorRecord)。
    6. valueCompletion(Get(next, "1"))。
    7. IfAbruptCloseIterator(value, iteratorRecord)。
    8. statusCompletion(Call(adder, target, « key, value »))。
    9. IfAbruptCloseIterator(status, iteratorRecord)。
Note

期望参数 iterable 是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个迭代器对象,产生一个双元素类数组对象,其第一个元素是将用作 Map 键的值,第二个元素是要与该键关联的值。

24.1.2 Map 构造器的属性

Map 构造器

24.1.2.1 Map.groupBy ( items, callback )

Note

callback 应是一个接受两个参数的函数。groupBy 按升序对 items 中的每个元素调用一次 callback,并构造一个新的 Map。callback 返回的每个值都用作 Map 中的键。对于每个这样的键,结果 Map 都有一个条目,其键为该键,其值为一个数组,包含所有使 callback 返回该键的元素。

调用 callback 时传入两个参数:元素的值和元素的索引。

groupBy 的返回值是一个 Map。

此函数在被调用时执行以下步骤:

  1. groups 为 ? GroupBy(items, callback, collection)。
  2. map 为 ! Construct(%Map%)。
  3. 对于 groups 的每个 Record { [[Key]], [[Elements]] } group,执行
    1. elementsCreateArrayFromList(group.[[Elements]])。
    2. entryRecord { [[Key]]: group.[[Key]], [[Value]]: elements }。
    3. entry 追加到 map.[[MapData]]
  4. 返回 map

24.1.2.2 Map.prototype

Map.prototype 的初始值是 Map 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.1.2.3 get Map [ %Symbol.species% ]

Map[%Symbol.species%] 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值为 "get [Symbol.species]"

Note

创建派生集合对象的方法应调用 %Symbol.species%,以确定用于创建派生对象的构造器。子类构造器可以覆写 %Symbol.species% 以更改默认构造器分配。

24.1.3 Map 原型对象的属性

Map 原型对象

24.1.3.1 Map.prototype.clear ( )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. entry.[[Key]] 设置为 empty
    2. entry.[[Value]] 设置为 empty
  4. 返回 undefined
Note

保留现有的 [[MapData]] List,因为可能存在已在遍历该 List 的中途挂起的 Map Iterator 对象。

24.1.3.2 Map.prototype.constructor

Map.prototype.constructor 的初始值是 %Map%

24.1.3.3 Map.prototype.delete ( key )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Key]] 设置为 empty
      2. entry.[[Value]] 设置为 empty
      3. 返回 true
  5. 返回 false
Note

empty 用作规范装置,以指示一个条目已被删除。实际实现可以采取其他动作,例如从内部数据结构中物理移除该条目。

24.1.3.4 Map.prototype.entries ( )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 返回 ? CreateMapIterator(map, key+value)。

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

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  4. entriesmap.[[MapData]]
  5. numEntriesentries 中元素的数量。
  6. index 为 0。
  7. 重复,当 index < numEntries 时,
    1. eentries[index]。
    2. index 设置为 index + 1。
    3. 如果 e.[[Key]] 不是 empty,则
      1. 执行 ? Call(callback, thisArg, « e.[[Value]], e.[[Key]], map »)。
      2. 注:在执行 callback 期间,entries 中的元素数量可能已增加。
      3. numEntries 设置为 entries 中元素的数量。
  8. 返回 undefined
Note

callback 应是一个接受三个参数的函数。forEach 按键插入顺序对 Map 中存在的每个键/值对调用一次 callbackcallback 只会针对 Map 中实际存在的键调用;不会针对已从 Map 中删除的键调用。

如果提供了 thisArg 参数,则它将用作每次调用 callback 时的 this 值。如果未提供,则使用 undefined

调用 callback 时传入三个参数:项的值、项的键以及正在遍历的 Map。

forEach 不会直接改变调用它的对象,但该对象可能会被对 callback 的调用改变。map 的 [[MapData]] 中的每个条目只会被访问一次。在 forEach 调用开始后添加的新键会被访问。某个键如果在被访问后被删除,然后在 forEach 调用完成前重新添加,则会被再次访问。在 forEach 调用开始后且被访问之前被删除的键不会被访问,除非该键在 forEach 调用完成前再次被添加。

24.1.3.6 Map.prototype.get ( key )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 entry.[[Value]]
  5. 返回 undefined

24.1.3.7 Map.prototype.getOrInsert ( key, value )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 entry.[[Value]]
  5. entryRecord { [[Key]]: key, [[Value]]: value }。
  6. entry 追加到 map.[[MapData]]
  7. 返回 value

24.1.3.8 Map.prototype.getOrInsertComputed ( key, callback )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  4. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  5. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 entry.[[Value]]
  6. value 为 ? Call(callback, undefined, « key »)。
  7. 注:在执行 callback 期间,Map 可能已被修改。
  8. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Value]] 设置为 value
      2. 返回 value
  9. entryRecord { [[Key]]: key, [[Value]]: value }。
  10. entry 追加到 map.[[MapData]]
  11. 返回 value

24.1.3.9 Map.prototype.has ( key )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 true
  5. 返回 false

24.1.3.10 Map.prototype.keys ( )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 返回 ? CreateMapIterator(map, key)。

24.1.3.11 Map.prototype.set ( key, value )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Value]] 设置为 value
      2. 返回 map
  5. entryRecord { [[Key]]: key, [[Value]]: value }。
  6. entry 追加到 map.[[MapData]]
  7. 返回 map

24.1.3.12 get Map.prototype.size

Map.prototype.size 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. count 为 0。
  4. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty,将 count 设置为 count + 1。
  5. 返回 𝔽(count)。

24.1.3.13 Map.prototype.values ( )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 返回 ? CreateMapIterator(map, value)。

24.1.3.14 Map.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值为 %Map.prototype.entries%,定义见 24.1.3.4

24.1.3.15 Map.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Map"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.1.4 Map 实例的属性

Map 实例是普通对象,从 Map 原型对象继承属性。Map 实例还具有 [[MapData]] 内部槽。

24.1.5 Map Iterator 对象

Map Iterator 是一个对象,表示对某个特定 Map 实例对象进行的特定迭代。Map Iterator 对象没有具名构造器。相反,Map Iterator 对象是通过调用 Map 实例对象的某些方法创建的。

24.1.5.1 CreateMapIterator ( map, kind )

The abstract operation CreateMapIterator takes arguments map (一个 ECMAScript 语言值,) and kind (key+valuekeyvalue,) and returns 要么是一个包含 Generator 的正常完成,要么是一个抛出完成. 它用于为返回此类迭代器的 Map 方法创建迭代器对象。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(map, [[MapData]])。
  2. closure 为一个新的无参数 Abstract Closure,捕获 mapkind,并在被调用时执行以下步骤:
    1. entriesmap.[[MapData]]
    2. index 为 0。
    3. numEntriesentries 中元素的数量。
    4. 重复,当 index < numEntries 时,
      1. entryentries[index]。
      2. index 设置为 index + 1。
      3. 如果 entry.[[Key]] 不是 empty,则
        1. 如果 kindkey,则
          1. resultentry.[[Key]]
        2. 否则如果 kindvalue,则
          1. resultentry.[[Value]]
        3. 否则,
          1. 断言:kindkey+value
          2. resultCreateArrayFromListentry.[[Key]], entry.[[Value]] »)。
        4. 执行 ? GeneratorYield(CreateIteratorResultObject(result, false))。
        5. 注:当此抽象操作的执行被 GeneratorYield 暂停时,entries 中的元素数量可能已增加。
        6. numEntries 设置为 entries 中元素的数量。
    5. 返回 NormalCompletion(unused)。
  3. 返回 CreateIteratorFromClosure(closure, "%MapIteratorPrototype%", %MapIteratorPrototype%)。

24.1.5.2 %MapIteratorPrototype% 对象

%MapIteratorPrototype% 对象:

24.1.5.2.1 %MapIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this value, empty, "%MapIteratorPrototype%")。

24.1.5.2.2 %MapIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Map Iterator"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.2 Set 对象

Set 对象ECMAScript 语言值的集合。一个 Set 最多只能包含每个不同值一次。不同值使用 SameValueZero 比较算法的语义加以区分。

Set 对象必须使用哈希表或其他机制来实现,这些机制平均而言能提供相对于集合中元素数量为次线性的访问时间。本规范中使用的数据结构仅用于描述 Set 对象所要求的可观察语义。它并不意图作为可行的实现模型。

24.2.1 Set 对象的抽象操作

24.2.1.1 Set Record

Set Record 是一个 Record 值,用于封装 Set 或类似对象的接口。

Set Record 具有 Table 71 中列出的字段。

Table 71: Set Record 字段
字段名 含义
[[SetObject]] 一个 Object 该 Set 或类似对象。
[[Size]] 一个非负整数或 +∞ 该对象报告的大小。
[[Has]] 一个函数对象 该对象的 has 方法。
[[Keys]] 一个函数对象 该对象的 keys 方法。

24.2.1.2 GetSetRecord ( obj )

The abstract operation GetSetRecord takes argument obj (一个 ECMAScript 语言值,) and returns 要么是一个包含 Set Record正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 obj 不是 Object,抛出 TypeError 异常。
  2. rawSize 为 ? Get(obj, "size")。
  3. numSize 为 ? ToNumber(rawSize)。
  4. 注:如果 rawSizeundefined,则 numSize 将是 NaN
  5. 如果 numSizeNaN,抛出 TypeError 异常。
  6. intSize 为 ! ToIntegerOrInfinity(numSize)。
  7. 如果 intSize < 0,抛出 RangeError 异常。
  8. has 为 ? Get(obj, "has")。
  9. 如果 IsCallable(has) 是 false,抛出 TypeError 异常。
  10. keys 为 ? Get(obj, "keys")。
  11. 如果 IsCallable(keys) 是 false,抛出 TypeError 异常。
  12. 返回一个新的 Set Record { [[SetObject]]: obj, [[Size]]: intSize, [[Has]]: has, [[Keys]]: keys }。

24.2.1.3 SetDataHas ( setData, value )

The abstract operation SetDataHas takes arguments setData (一个由 ECMAScript 语言值empty 组成的 List,) and value (一个 ECMAScript 语言值,) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 SetDataIndex(setData, value) 是 not-found,返回 false
  2. 返回 true

24.2.1.4 SetDataIndex ( setData, value )

The abstract operation SetDataIndex takes arguments setData (一个由 ECMAScript 语言值empty 组成的 List,) and value (一个 ECMAScript 语言值,) and returns 一个非负整数not-found. It performs the following steps when called:

  1. value 设置为 CanonicalizeKeyedCollectionKey(value)。
  2. sizesetData 中元素的数量。
  3. index 为 0。
  4. 重复,当 index < size 时,
    1. esetData[index]。
    2. 如果 e 不是 emptyevalue,则
      1. 返回 index
    3. index 设置为 index + 1。
  5. 返回 not-found

24.2.1.5 SetDataSize ( setData )

The abstract operation SetDataSize takes argument setData (一个由 ECMAScript 语言值empty 组成的 List,) and returns 一个非负整数. It performs the following steps when called:

  1. count 为 0。
  2. 对于 setData 的每个元素 e,执行
    1. 如果 e 不是 empty,将 count 设置为 count + 1。
  3. 返回 count

24.2.2 Set 构造器

Set 构造器

  • %Set%
  • 全局对象"Set" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 Set 对象
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 Set 行为的子类构造器必须包含对 Set 构造器super 调用,以创建并初始化带有支持 Set.prototype 内置方法所需内部状态的子类实例。

24.2.2.1 Set ( [ iterable ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. set 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Set.prototype%", « [[SetData]] »)。
  3. set.[[SetData]] 设置为一个新的空 List
  4. 如果 iterableundefinednull,返回 set
  5. adder 为 ? Get(set, "add")。
  6. 如果 IsCallable(adder) 是 false,抛出 TypeError 异常。
  7. iteratorRecord 为 ? GetIterator(iterable, sync)。
  8. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 set
    3. statusCompletion(Call(adder, set, « next »))。
    4. IfAbruptCloseIterator(status, iteratorRecord)。

24.2.3 Set 构造器的属性

Set 构造器

24.2.3.1 Set.prototype

Set.prototype 的初始值是 Set 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.2.3.2 get Set [ %Symbol.species% ]

Set[%Symbol.species%] 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值为 "get [Symbol.species]"

Note

创建派生集合对象的方法应调用 %Symbol.species%,以确定用于创建派生对象的构造器。子类构造器可以覆写 %Symbol.species% 以更改默认构造器分配。

24.2.4 Set 原型对象的属性

Set 原型对象

24.2.4.1 Set.prototype.add ( value )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. 对于 set.[[SetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,则
      1. 返回 set
  5. value 追加到 set.[[SetData]]
  6. 返回 set

24.2.4.2 Set.prototype.clear ( )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 对于 set.[[SetData]] 的每个元素 entry,执行
    1. set.[[SetData]] 中值为 entry 的元素替换为值为 empty 的元素。
  4. 返回 undefined
Note

保留现有的 [[SetData]] List,因为可能存在已在遍历该 List 的中途挂起的 Set Iterator 对象。

24.2.4.3 Set.prototype.constructor

Set.prototype.constructor 的初始值是 %Set%

24.2.4.4 Set.prototype.delete ( value )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. 对于 set.[[SetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,则
      1. set.[[SetData]] 中值为 entry 的元素替换为值为 empty 的元素。
      2. 返回 true
  5. 返回 false
Note

empty 用作规范装置,以指示一个条目已被删除。实际实现可以采取其他动作,例如从内部数据结构中物理移除该条目。

24.2.4.5 Set.prototype.difference ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. resultSetDataset.[[SetData]] 的副本。
  5. 如果 SetDataSize(set.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeset.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. 重复,当 index < thisSize 时,
      1. entryresultSetData[index]。
      2. 如果 entry 不是 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « entry »))。
        2. 如果 inOthertrue,则
          1. resultSetData[index] 设置为 empty
      3. index 设置为 index + 1。
  6. 否则,
    1. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
    2. nextnot-started
    3. 重复,当 next 不是 done 时,
      1. next 设置为 ? IteratorStepValue(keysIter)。
      2. 如果 next 不是 done,则
        1. next 设置为 CanonicalizeKeyedCollectionKey(next)。
        2. valueIndexSetDataIndex(resultSetData, next)。
        3. 如果 valueIndex 不是 not-found,则
          1. resultSetData[valueIndex] 设置为 empty
  7. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  8. result.[[SetData]] 设置为 resultSetData
  9. 返回 result

24.2.4.6 Set.prototype.entries ( )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 返回 ? CreateSetIterator(set, key+value)。
Note

为迭代目的,Set 看起来类似于一个 Map,其中每个条目的键和值具有相同的值。

24.2.4.7 Set.prototype.forEach ( callback [ , thisArg ] )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  4. entriesset.[[SetData]]
  5. numEntriesentries 中元素的数量。
  6. index 为 0。
  7. 重复,当 index < numEntries 时,
    1. entryentries[index]。
    2. index 设置为 index + 1。
    3. 如果 entry 不是 empty,则
      1. 执行 ? Call(callback, thisArg, « entry, entry, set »)。
      2. 注:在执行 callback 期间,entries 中的元素数量可能已增加。
      3. numEntries 设置为 entries 中元素的数量。
  8. 返回 undefined
Note

callback 应是一个接受三个参数的函数。forEach 按值插入顺序对 Set 对象中存在的每个值调用一次 callbackcallback 只会针对 Set 中实际存在的值调用;不会针对已从 set 中删除的键调用。

如果提供了 thisArg 参数,则它将用作每次调用 callback 时的 this 值。如果未提供,则使用 undefined

调用 callback 时传入三个参数:前两个参数是 Set 中包含的一个值。两个参数传入相同的值。正在遍历的 Set 对象作为第三个参数传入。

callback 以三个参数调用,是为了与 Map 和 Array 的 forEach 方法所使用的回调函数保持一致。对于 Set,每个项值都被视为键和值。

forEach 不会直接改变调用它的对象,但该对象可能会被对 callback 的调用改变。

通常每个值只会被访问一次。然而,如果某个值在被访问后被删除,然后在 forEach 调用完成前重新添加,则该值会被再次访问。在 forEach 调用开始后且被访问之前被删除的值不会被访问,除非该值在 forEach 调用完成前再次被添加。在 forEach 调用开始后添加的新值会被访问。

24.2.4.8 Set.prototype.has ( value )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. 对于 set.[[SetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,返回 true
  5. 返回 false

24.2.4.9 Set.prototype.intersection ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. resultSetData 为一个新的空 List
  5. 如果 SetDataSize(set.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeset.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. 重复,当 index < thisSize 时,
      1. entryset.[[SetData]][index]。
      2. index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « entry »))。
        2. 如果 inOthertrue,则
          1. 注:较早的 otherRec.[[Has]] 调用可能移除并重新添加 set.[[SetData]] 的一个元素,这可能导致同一元素在此迭代期间被访问两次。
          2. 如果 SetDataHas(resultSetData, entry) 是 false,则
            1. entry 追加到 resultSetData
        3. 注:在执行 otherRec.[[Has]] 期间,set.[[SetData]] 中的元素数量可能已增加。
        4. thisSize 设置为 set.[[SetData]] 中元素的数量。
  6. 否则,
    1. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
    2. nextnot-started
    3. 重复,当 next 不是 done 时,
      1. next 设置为 ? IteratorStepValue(keysIter)。
      2. 如果 next 不是 done,则
        1. next 设置为 CanonicalizeKeyedCollectionKey(next)。
        2. inThisSetDataHas(set.[[SetData]], next)。
        3. 如果 inThistrue,则
          1. 注:因为 other 是任意对象,所以其 "keys" 迭代器可能多次产生相同的值。
          2. 如果 SetDataHas(resultSetData, next) 是 false,则
            1. next 追加到 resultSetData
  7. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  8. result.[[SetData]] 设置为 resultSetData
  9. 返回 result

24.2.4.10 Set.prototype.isDisjointFrom ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeset.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. 重复,当 index < thisSize 时,
      1. entryset.[[SetData]][index]。
      2. index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « entry »))。
        2. 如果 inOthertrue,返回 false
        3. 注:在执行 otherRec.[[Has]] 期间,set.[[SetData]] 中的元素数量可能已增加。
        4. thisSize 设置为 set.[[SetData]] 中元素的数量。
  5. 否则,
    1. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
    2. nextnot-started
    3. 重复,当 next 不是 done 时,
      1. next 设置为 ? IteratorStepValue(keysIter)。
      2. 如果 next 不是 done,则
        1. 如果 SetDataHas(set.[[SetData]], next) 是 true,则
          1. 执行 ? IteratorClose(keysIter, NormalCompletion(unused))。
          2. 返回 false
  6. 返回 true

24.2.4.11 Set.prototype.isSubsetOf ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) > otherRec.[[Size]],返回 false
  5. thisSizeset.[[SetData]] 中元素的数量。
  6. index 为 0。
  7. 重复,当 index < thisSize 时,
    1. entryset.[[SetData]][index]。
    2. index 设置为 index + 1。
    3. 如果 entry 不是 empty,则
      1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « entry »))。
      2. 如果 inOtherfalse,返回 false
      3. 注:在执行 otherRec.[[Has]] 期间,set.[[SetData]] 中的元素数量可能已增加。
      4. thisSize 设置为 set.[[SetData]] 中元素的数量。
  8. 返回 true

24.2.4.12 Set.prototype.isSupersetOf ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) < otherRec.[[Size]],返回 false
  5. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  6. nextnot-started
  7. 重复,当 next 不是 done 时,
    1. next 设置为 ? IteratorStepValue(keysIter)。
    2. 如果 next 不是 done,则
      1. 如果 SetDataHas(set.[[SetData]], next) 是 false,则
        1. 执行 ? IteratorClose(keysIter, NormalCompletion(unused))。
        2. 返回 false
  8. 返回 true

24.2.4.13 Set.prototype.keys ( )

"keys" 属性的初始值为 %Set.prototype.values%,定义见 24.2.4.17

Note

为迭代目的,Set 看起来类似于一个 Map,其中每个条目的键和值具有相同的值。

24.2.4.14 get Set.prototype.size

Set.prototype.size 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. sizeSetDataSize(set.[[SetData]])。
  4. 返回 𝔽(size)。

24.2.4.15 Set.prototype.symmetricDifference ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  5. resultSetDataset.[[SetData]] 的副本。
  6. nextnot-started
  7. 重复,当 next 不是 done 时,
    1. next 设置为 ? IteratorStepValue(keysIter)。
    2. 如果 next 不是 done,则
      1. next 设置为 CanonicalizeKeyedCollectionKey(next)。
      2. resultIndexSetDataIndex(resultSetData, next)。
      3. 如果 resultIndexnot-found,令 alreadyInResultfalse;否则令 alreadyInResulttrue
      4. 如果 SetDataHas(set.[[SetData]], next) 是 true,则
        1. 如果 alreadyInResulttrue,将 resultSetData[resultIndex] 设置为 empty
      5. 否则,
        1. 如果 alreadyInResultfalse,将 next 追加到 resultSetData
  8. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  9. result.[[SetData]] 设置为 resultSetData
  10. 返回 result

24.2.4.16 Set.prototype.union ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  5. resultSetDataset.[[SetData]] 的副本。
  6. nextnot-started
  7. 重复,当 next 不是 done 时,
    1. next 设置为 ? IteratorStepValue(keysIter)。
    2. 如果 next 不是 done,则
      1. next 设置为 CanonicalizeKeyedCollectionKey(next)。
      2. 如果 SetDataHas(resultSetData, next) 是 false,则
        1. next 追加到 resultSetData
  8. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  9. result.[[SetData]] 设置为 resultSetData
  10. 返回 result

24.2.4.17 Set.prototype.values ( )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 返回 ? CreateSetIterator(set, value)。

24.2.4.18 Set.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值为 %Set.prototype.values%,定义见 24.2.4.17

24.2.4.19 Set.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Set"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.2.5 Set 实例的属性

Set 实例是普通对象,从 Set 原型对象继承属性。Set 实例还具有 [[SetData]] 内部槽。

24.2.6 Set Iterator 对象

Set Iterator 是一个普通对象,具有下文定义的结构,表示对某个特定 Set 实例对象进行的特定迭代。Set Iterator 对象没有具名构造器。相反,Set Iterator 对象是通过调用 Set 实例对象的某些方法创建的。

24.2.6.1 CreateSetIterator ( set, kind )

The abstract operation CreateSetIterator takes arguments set (一个 ECMAScript 语言值,) and kind (key+valuevalue,) and returns 要么是一个包含 Generator 的正常完成,要么是一个抛出完成. 它用于为返回此类迭代器的 Set 方法创建迭代器对象。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(set, [[SetData]])。
  2. closure 为一个新的无参数 Abstract Closure,捕获 setkind,并在被调用时执行以下步骤:
    1. index 为 0。
    2. entriesset.[[SetData]]
    3. numEntriesentries 中元素的数量。
    4. 重复,当 index < numEntries 时,
      1. entryentries[index]。
      2. index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. 如果 kindkey+value,则
          1. resultCreateArrayFromListentry, entry »)。
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(result, false))。
        2. 否则,
          1. 断言:kindvalue
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(entry, false))。
        3. 注:当此抽象操作的执行被 GeneratorYield 暂停时,entries 中的元素数量可能已增加。
        4. numEntries 设置为 entries 中元素的数量。
    5. 返回 NormalCompletion(unused)。
  3. 返回 CreateIteratorFromClosure(closure, "%SetIteratorPrototype%", %SetIteratorPrototype%)。

24.2.6.2 %SetIteratorPrototype% 对象

%SetIteratorPrototype% 对象:

24.2.6.2.1 %SetIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this value, empty, "%SetIteratorPrototype%")。

24.2.6.2.2 %SetIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Set Iterator"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.3 WeakMap 对象

WeakMap 是键/值对的集合,其中键是对象和/或符号,值可以是任意 ECMAScript 语言值。可以查询 WeakMap 以查看它是否包含具有特定键的键/值对,但不提供枚举它作为键所持有的值的机制。在某些条件下,不再存活的值会作为 WeakMap 键被移除,如 9.9.3 中所述。

实现可以在 WeakMap 的某个键/值对变得不可访问的时间与该键/值对从 WeakMap 中移除的时间之间施加任意确定的延迟。如果此延迟可被 ECMAScript 程序观察到,它将成为一种可能影响程序执行的不确定性来源。因此,ECMAScript 实现不得提供任何手段来观察 WeakMap 的某个键,除非该观察要求观察者提供被观察的键。

WeakMap 必须使用哈希表或其他机制来实现,这些机制平均而言能提供相对于集合中键/值对数量为次线性的访问时间。本规范中使用的数据结构仅用于描述 WeakMap 所要求的可观察语义。它并不意图作为可行的实现模型。

Note

WeakMap 和 WeakSet 意图提供一种机制,用于以不会“泄漏”内存资源的方式动态地将状态与对象或符号关联起来;也就是说,如果没有 WeakMap 或 WeakSet 实例,该对象或符号本来会变得不可访问并受实现的垃圾收集机制回收。此特性可以通过使用 WeakMap 或 WeakSet 实例到键的反向每对象/符号映射来实现。或者,每个 WeakMap 或 WeakSet 实例也可以在内部存储其键和值数据,但这种方式要求 WeakMap 或 WeakSet 实现与垃圾收集器协调。以下参考文献描述了可能对 WeakMap 和 WeakSet 实现有用的机制:

Barry Hayes. 1997. Ephemerons: a new finalization mechanism. In Proceedings of the 12th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications (OOPSLA '97), A. Michael Berman (Ed.). ACM, New York, NY, USA, 176-183, http://doi.acm.org/10.1145/263698.263733.

Alexandra Barros, Roberto Ierusalimschy, Eliminating Cycles in Weak Tables. Journal of Universal Computer Science - J.UCS, vol. 14, no. 21, pp. 3481-3497, 2008, http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak

24.3.1 WeakMap 构造器

WeakMap 构造器

  • %WeakMap%
  • 全局对象"WeakMap" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 WeakMap。
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 WeakMap 行为的子类构造器必须包含对 WeakMap 构造器super 调用,以创建并初始化带有支持 WeakMap.prototype 内置方法所需内部状态的子类实例。

24.3.1.1 WeakMap ( [ iterable ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. map 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakMap.prototype%", « [[WeakMapData]] »)。
  3. map.[[WeakMapData]] 设置为一个新的空 List
  4. 如果 iterableundefinednull,返回 map
  5. adder 为 ? Get(map, "set")。
  6. 如果 IsCallable(adder) 是 false,抛出 TypeError 异常。
  7. 返回 ? AddEntriesFromIterable(map, iterable, adder)。
Note

如果存在参数 iterable,则期望它是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个迭代器对象,产生一个双元素类数组对象,其第一个元素是将用作 WeakMap 键的值,第二个元素是要与该键关联的值。

24.3.2 WeakMap 构造器的属性

WeakMap 构造器

24.3.2.1 WeakMap.prototype

WeakMap.prototype 的初始值是 WeakMap 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.3.3 WeakMap 原型对象的属性

WeakMap 原型对象

  • %WeakMap.prototype%
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个普通对象
  • 没有 [[WeakMapData]] 内部槽。

24.3.3.1 WeakMap.prototype.constructor

WeakMap.prototype.constructor 的初始值是 %WeakMap%

24.3.3.2 WeakMap.prototype.delete ( key )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,返回 false
  4. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Key]] 设置为 empty
      2. entry.[[Value]] 设置为 empty
      3. 返回 true
  5. 返回 false
Note

empty 用作规范装置,以指示一个条目已被删除。实际实现可以采取其他动作,例如从内部数据结构中物理移除该条目。

24.3.3.3 WeakMap.prototype.get ( key )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,返回 undefined
  4. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 entry.[[Value]]
  5. 返回 undefined

24.3.3.4 WeakMap.prototype.getOrInsert ( key, value )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,抛出 TypeError 异常。
  4. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 entry.[[Value]]
  5. entryRecord { [[Key]]: key, [[Value]]: value }。
  6. entry 追加到 weakMap.[[WeakMapData]]
  7. 返回 value

24.3.3.5 WeakMap.prototype.getOrInsertComputed ( key, callback )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,抛出 TypeError 异常。
  4. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  5. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 entry.[[Value]]
  6. value 为 ? Call(callback, undefined, « key »)。
  7. 注:在执行 callback 期间,WeakMap 可能已被修改。
  8. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Value]] 设置为 value
      2. 返回 value
  9. entryRecord { [[Key]]: key, [[Value]]: value }。
  10. entry 追加到 weakMap.[[WeakMapData]]
  11. 返回 value

24.3.3.6 WeakMap.prototype.has ( key )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,返回 false
  4. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 true
  5. 返回 false

24.3.3.7 WeakMap.prototype.set ( key, value )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,抛出 TypeError 异常。
  4. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Value]] 设置为 value
      2. 返回 weakMap
  5. entryRecord { [[Key]]: key, [[Value]]: value }。
  6. entry 追加到 weakMap.[[WeakMapData]]
  7. 返回 weakMap

24.3.3.8 WeakMap.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "WeakMap"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.3.4 WeakMap 实例的属性

WeakMap 实例是普通对象,从 WeakMap 原型对象继承属性。WeakMap 实例还具有 [[WeakMapData]] 内部槽。

24.4 WeakSet 对象

WeakSet 是对象和/或符号的集合。一个不同的对象或符号作为 WeakSet 集合的元素只能出现一次。可以查询 WeakSet 以查看它是否包含某个特定值,但不提供枚举它所持有的值的机制。在某些条件下,不再存活的值会作为 WeakSet 元素被移除,如 9.9.3 中所述。

实现可以在 WeakSet 中包含的某个值变得不可访问的时间与该值从 WeakSet 中移除的时间之间施加任意确定的延迟。如果此延迟可被 ECMAScript 程序观察到,它将成为一种可能影响程序执行的不确定性来源。因此,ECMAScript 实现不得提供任何手段来确定 WeakSet 是否包含某个特定值,除非该确定要求观察者提供被观察的值。

WeakSet 必须使用哈希表或其他机制来实现,这些机制平均而言能提供相对于集合中元素数量为次线性的访问时间。本规范中使用的数据结构仅用于描述 WeakSet 所要求的可观察语义。它并不意图作为可行的实现模型。

Note

24.3 中的注。

24.4.1 WeakSet 构造器

WeakSet 构造器

  • %WeakSet%
  • 全局对象"WeakSet" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 WeakSet。
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 WeakSet 行为的子类构造器必须包含对 WeakSet 构造器super 调用,以创建并初始化带有支持 WeakSet.prototype 内置方法所需内部状态的子类实例。

24.4.1.1 WeakSet ( [ iterable ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. set 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakSet.prototype%", « [[WeakSetData]] »)。
  3. set.[[WeakSetData]] 设置为一个新的空 List
  4. 如果 iterableundefinednull,返回 set
  5. adder 为 ? Get(set, "add")。
  6. 如果 IsCallable(adder) 是 false,抛出 TypeError 异常。
  7. iteratorRecord 为 ? GetIterator(iterable, sync)。
  8. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 set
    3. statusCompletion(Call(adder, set, « next »))。
    4. IfAbruptCloseIterator(status, iteratorRecord)。

24.4.2 WeakSet 构造器的属性

WeakSet 构造器

24.4.2.1 WeakSet.prototype

WeakSet.prototype 的初始值是 WeakSet 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.4.3 WeakSet 原型对象的属性

WeakSet 原型对象

  • %WeakSet.prototype%
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个普通对象
  • 没有 [[WeakSetData]] 内部槽。

24.4.3.1 WeakSet.prototype.add ( value )

此方法在被调用时执行以下步骤:

  1. weakSetthis 值。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,抛出 TypeError 异常。
  4. 对于 weakSet.[[WeakSetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,则
      1. 返回 weakSet
  5. value 追加到 weakSet.[[WeakSetData]]
  6. 返回 weakSet

24.4.3.2 WeakSet.prototype.constructor

WeakSet.prototype.constructor 的初始值是 %WeakSet%

24.4.3.3 WeakSet.prototype.delete ( value )

此方法在被调用时执行以下步骤:

  1. weakSetthis 值。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,返回 false
  4. 对于 weakSet.[[WeakSetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,则
      1. weakSet.[[WeakSetData]] 中值为 entry 的元素替换为值为 empty 的元素。
      2. 返回 true
  5. 返回 false
Note

empty 用作规范装置,以指示一个条目已被删除。实际实现可以采取其他动作,例如从内部数据结构中物理移除该条目。

24.4.3.4 WeakSet.prototype.has ( value )

此方法在被调用时执行以下步骤:

  1. weakSetthis 值。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,返回 false
  4. 对于 weakSet.[[WeakSetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,返回 true
  5. 返回 false

24.4.3.5 WeakSet.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "WeakSet"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.4.4 WeakSet 实例的属性

WeakSet 实例是普通对象,从 WeakSet 原型对象继承属性。WeakSet 实例还具有 [[WeakSetData]] 内部槽。

24.5 键控集合的抽象操作

24.5.1 CanonicalizeKeyedCollectionKey ( key )

The abstract operation CanonicalizeKeyedCollectionKey takes argument key (一个 ECMAScript 语言值,) and returns 一个 ECMAScript 语言值. It performs the following steps when called:

  1. 如果 key-0𝔽,返回 +0𝔽
  2. 返回 key