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. entriesCountentries 中元素的数量。
  6. index 为 0。
  7. 重复,只要 index < entriesCount
    1. entryentries[index]。
    2. index 设置为 index + 1。
    3. 如果 entry.[[Key]] 不是 empty,则
      1. 执行 ? Call(callback, thisArg, « entry.[[Value]], entry.[[Key]], map »)。
      2. 注:entries 中元素的数量可能已在 callback 执行期间增加。
      3. entriesCount 设置为 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. 注:Map 可能已在 callback 执行期间被修改。
  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 (an ECMAScript language value) and kind (key+value, key, or value) and returns either a normal completion containing a Generator or a throw completion. 它用于为返回此类迭代器的 Map 方法创建迭代器对象。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(map, [[MapData]])。
  2. closure 为一个新的无参数 Abstract Closure,它捕获 mapkind,并在被调用时执行以下步骤:
    1. entriesmap.[[MapData]]
    2. index 为 0。
    3. entriesCountentries 中元素的数量。
    4. 重复,只要 index < entriesCount
      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. entriesCount 设置为 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 72 中列出的字段。

Table 72: Set Record 字段
字段名 含义
[[SetObject]] an Object Set 或类似对象。
[[Size]] a non-negative integer or +∞ 对象报告的大小。
[[Has]] a function object 对象的 has 方法。
[[Keys]] a function object 对象的 keys 方法。

24.2.1.2 GetSetRecord ( obj )

The abstract operation GetSetRecord takes argument obj (an ECMAScript language value) and returns either a normal completion containing a Set Record or a throw completion. It performs the following steps when called:

  1. 如果 obj 不是 Object,则抛出 TypeError 异常。
  2. rawSize 为 ? Get(obj, "size")。
  3. numberSize 为 ? ToNumber(rawSize)。
  4. 注:如果 rawSizeundefined,则 numberSize 将是 NaN
  5. 如果 numberSizeNaN,则抛出 TypeError 异常。
  6. intSize 为 ! ToIntegerOrInfinity(numberSize)。
  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 (a List of either ECMAScript language values or empty) and value (an ECMAScript language value) and returns a 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 (a List of either ECMAScript language values or empty) and value (an ECMAScript language value) and returns a non-negative integer or not-found. It performs the following steps when called:

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

24.2.1.5 SetDataSize ( setData )

The abstract operation SetDataSize takes argument setData (a List of either ECMAScript language values or empty) and returns a non-negative integer. It performs the following steps when called:

  1. count 为 0。
  2. setData 的每个元素 element,执行:
    1. 如果 element 不是 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. otherRecord 为 ? GetSetRecord(other)。
  4. resultSetDataset.[[SetData]] 的一个副本。
  5. 如果 SetDataSize(set.[[SetData]]) ≤ otherRecord.[[Size]],则
    1. thisSizeset.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. 重复,只要 index < thisSize
      1. entryresultSetData[index]。
      2. 如果 entry 不是 empty,则
        1. inOtherToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
        2. 如果 inOthertrue,则
          1. resultSetData[index] 设置为 empty
      3. index 设置为 index + 1。
  6. 否则,
    1. keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
    2. nextnot-started
    3. 重复,只要 next 不是 done
      1. next 设置为 ? IteratorStepValue(keysIterator)。
      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. entriesCountentries 中元素的数量。
  6. index 为 0。
  7. 重复,只要 index < entriesCount
    1. entryentries[index]。
    2. index 设置为 index + 1。
    3. 如果 entry 不是 empty,则
      1. 执行 ? Call(callback, thisArg, « entry, entry, set »)。
      2. 注:entries 中元素的数量可能已在 callback 执行期间增加。
      3. entriesCount 设置为 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. otherRecord 为 ? GetSetRecord(other)。
  4. resultSetData 为新的空 List
  5. 如果 SetDataSize(set.[[SetData]]) ≤ otherRecord.[[Size]],则
    1. thisSizeset.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. 重复,只要 index < thisSize
      1. entryset.[[SetData]][index]。
      2. index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. inOtherToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
        2. 如果 inOthertrue,则
          1. 注:先前对 otherRecord.[[Has]] 的调用可能会移除并重新添加 set.[[SetData]] 的一个元素,这可能导致同一个元素在此次迭代期间被访问两次。
          2. 如果 SetDataHas(resultSetData, entry) 是 false,则
            1. entry 追加到 resultSetData
        3. 注:set.[[SetData]] 中元素的数量可能已在 otherRecord.[[Has]] 执行期间增加。
        4. thisSize 设置为 set.[[SetData]] 中元素的数量。
  6. 否则,
    1. keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
    2. nextnot-started
    3. 重复,只要 next 不是 done
      1. next 设置为 ? IteratorStepValue(keysIterator)。
      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. otherRecord 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) ≤ otherRecord.[[Size]],则
    1. thisSizeset.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. 重复,只要 index < thisSize
      1. entryset.[[SetData]][index]。
      2. index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. inOtherToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
        2. 如果 inOthertrue,则返回 false
        3. 注:set.[[SetData]] 中元素的数量可能已在 otherRecord.[[Has]] 执行期间增加。
        4. thisSize 设置为 set.[[SetData]] 中元素的数量。
  5. 否则,
    1. keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
    2. nextnot-started
    3. 重复,只要 next 不是 done
      1. next 设置为 ? IteratorStepValue(keysIterator)。
      2. 如果 next 不是 done,则
        1. 如果 SetDataHas(set.[[SetData]], next) 是 true,则
          1. 执行 ? IteratorClose(keysIterator, NormalCompletion(unused))。
          2. 返回 false
  6. 返回 true

24.2.4.11 Set.prototype.isSubsetOf ( other )

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

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRecord 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) > otherRecord.[[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(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
      2. 如果 inOtherfalse,则返回 false
      3. 注:set.[[SetData]] 中元素的数量可能已在 otherRecord.[[Has]] 执行期间增加。
      4. thisSize 设置为 set.[[SetData]] 中元素的数量。
  8. 返回 true

24.2.4.12 Set.prototype.isSupersetOf ( other )

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

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRecord 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) < otherRecord.[[Size]],则返回 false
  5. keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
  6. nextnot-started
  7. 重复,只要 next 不是 done
    1. next 设置为 ? IteratorStepValue(keysIterator)。
    2. 如果 next 不是 done,则
      1. 如果 SetDataHas(set.[[SetData]], next) 是 false,则
        1. 执行 ? IteratorClose(keysIterator, 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. otherRecord 为 ? GetSetRecord(other)。
  4. keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
  5. resultSetDataset.[[SetData]] 的一个副本。
  6. nextnot-started
  7. 重复,只要 next 不是 done
    1. next 设置为 ? IteratorStepValue(keysIterator)。
    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. otherRecord 为 ? GetSetRecord(other)。
  4. keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
  5. resultSetDataset.[[SetData]] 的一个副本。
  6. nextnot-started
  7. 重复,只要 next 不是 done
    1. next 设置为 ? IteratorStepValue(keysIterator)。
    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 (an ECMAScript language value) and kind (key+value or value) and returns either a normal completion containing a Generator or a throw completion. 它用于为返回此类迭代器的 Set 方法创建迭代器对象。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(set, [[SetData]])。
  2. closure 为一个新的无参数 Abstract Closure,它捕获 setkind,并在被调用时执行以下步骤:
    1. index 为 0。
    2. entriesset.[[SetData]]
    3. entriesCountentries 中元素的数量。
    4. 重复,只要 index < entriesCount
      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. entriesCount 设置为 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 是键/值对的集合,其中键是对象和/或 symbol,值可以是任意 ECMAScript 语言值。可以查询 WeakMap,以查看它是否包含具有特定键的键/值对,但没有提供枚举它作为键所持有的值的机制。在某些条件下,非活动的值会作为 WeakMap 键被移除,如 9.9.3 中所述。

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

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

Note

WeakMap 和 WeakSet 旨在提供一种机制,用于以不会“泄漏”内存资源的方式,将状态动态关联到对象或 symbol;也就是说,如果没有 WeakMap 或 WeakSet 实例,该对象或 symbol 原本会变得不可访问,并受到实现的垃圾回收机制进行资源回收。可以通过使用 WeakMap 或 WeakSet 实例到键的反向每对象/symbol 映射来实现这一特性。或者,每个 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. 注:WeakMap 可能已在 callback 执行期间被修改。
  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 是对象和/或 symbol 的集合。一个不同的对象或 symbol 在 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 (an ECMAScript language value) and returns an ECMAScript language value. It performs the following steps when called:

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