页面模式偏好

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. 如果 iterable 是 undefined 或 null,则返回 map。
  5. 令 adder 为 ? Get(map, "set")。
  6. 如果 IsCallable(adder) 是 false,则抛出 TypeError 异常。
  7. 返回 ? AddEntriesFromIterable(map, iterable, adder)。
注

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

24.1.1.2 AddEntriesFromIterable ( target, iterable, adder )

抽象操作 AddEntriesFromIterable,接收参数 target (Object)、iterable (an ECMAScript language value, but not undefined or null) 和 adder (函数对象);返回值:(正常完成 (值:Object) 或 抛出完成)。 将以 target 作为接收者调用 adder。 调用时执行以下步骤:

  1. 令 iteratorRecord 为 ? GetIterator(iterable, sync)。
  2. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则返回 target。
    3. 如果 next 不是 Object,则
      1. 令 error 为 ThrowCompletion(a newly created TypeError object)。
      2. 返回 ? IteratorClose(iteratorRecord, error)。
    4. 令 key 为 Completion(Get(next, "0")).
    5. IfAbruptCloseIterator(key, iteratorRecord)。
    6. 令 value 为 Completion(Get(next, "1")).
    7. IfAbruptCloseIterator(value, iteratorRecord)。
    8. 令 status 为 Completion(Call(adder, target, « key, value »)).
    9. IfAbruptCloseIterator(status, iteratorRecord)。
注

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

24.1.2 Map 构造函数的属性

Map 构造函数:

24.1.2.1 Map.groupBy ( items, callback )

注

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. 令 elements 为 CreateArrayFromList(group.[[Elements]])。
    2. 令 entry 为 Record { [[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 value。

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

注

创建派生集合对象的方法应调用 %Symbol.species% 来确定用于创建派生对象的构造函数。子类构造函数可以覆盖 %Symbol.species% 以更改默认构造函数的指定。

24.1.3 Map 原型对象的属性

Map 原型对象:

24.1.3.1 Map.prototype.clear ( )

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

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 将 entry.[[Key]] 设置为 empty。
    2. 将 entry.[[Value]] 设置为 empty。
  4. 返回 undefined。
注

会保留现有的 [[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. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 将 key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则
      1. 将 entry.[[Key]] 设置为 empty。
      2. 将 entry.[[Value]] 设置为 empty。
      3. 返回 true。
  5. 返回 false。
注

值 empty 用作规范机制,以指示某个条目已被删除。实际实现可以采取其他操作,例如从内部数据结构中物理删除该条目。

24.1.3.4 Map.prototype.entries ( )

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

  1. 令 map 为 this value。
  2. 返回 ? CreateMapIterator(map, key+value)。

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

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

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

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

如果提供了 thisArg 参数,则每次调用 callback 时都会将其用作 this value。如果未提供,则改用 undefined。

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

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

24.1.3.6 Map.prototype.get ( key )

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

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 将 key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]。
  5. 返回 undefined。

24.1.3.7 Map.prototype.getOrInsert ( key, value )

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

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

24.1.3.8 Map.prototype.getOrInsertComputed ( key, callback )

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

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. 将 key 设置为 CanonicalizeKeyedCollectionKey(key)。
  5. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(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]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则
      1. 将 entry.[[Value]] 设置为 value。
      2. 返回 value。
  9. 令 entry 为 Record { [[Key]]: key, [[Value]]: value }。
  10. 将 entry 追加到 map.[[MapData]]。
  11. 返回 value。

24.1.3.9 Map.prototype.has ( key )

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

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 将 key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则返回 true。
  5. 返回 false。

24.1.3.10 Map.prototype.keys ( )

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

  1. 令 map 为 this value。
  2. 返回 ? CreateMapIterator(map, key)。

24.1.3.11 Map.prototype.set ( key, value )

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

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 将 key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则
      1. 将 entry.[[Value]] 设置为 value。
      2. 返回 map。
  5. 令 entry 为 Record { [[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. 令 map 为 this value。
  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. 令 map 为 this value。
  2. 返回 ? CreateMapIterator(map, value)。

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

%Symbol.iterator% 属性的初始值是 24.1.3.4 中定义的 %Map.prototype.entries%。

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 迭代器对象

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

24.1.5.1 CreateMapIterator ( map, kind )

抽象操作 CreateMapIterator,接收参数 map (ECMAScript 语言值) 和 kind ((key+value、key 或 value));返回值:(正常完成 (值:Generator) 或 抛出完成)。 它用于为返回此类迭代器的 Map 方法创建迭代器对象。 调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(map, [[MapData]])。
  2. 令 closure 为不带参数的新 Abstract Closure,它捕获 map 和 kind,并在被调用时执行以下步骤:
    1. 令 entries 为 map.[[MapData]]。
    2. 令 index 为 0。
    3. 令 entriesCount 为 entries 中的元素数量。
    4. 当 index < entriesCount 时,重复执行,
      1. 令 entry 为 entries[index]。
      2. 将 index 设置为 index + 1。
      3. 如果 entry.[[Key]] 不是 empty,则
        1. 如果 kind 是 key,则
          1. 令 result 为 entry.[[Key]]。
        2. 否则如果 kind 是 value,则
          1. 令 result 为 entry.[[Value]]。
        3. 否则,
          1. 断言:kind 是 key+value。
          2. 令 result 为 CreateArrayFromList(« entry.[[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 是用于封装 Set 或类似对象接口的 Record。

Set Record 具有 表 72 中列出的字段。

表 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 )

抽象操作 GetSetRecord,接收参数 obj (ECMAScript 语言值);返回值:(正常完成 (值:Set 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 obj 不是 Object,则抛出 TypeError 异常。
  2. 令 rawSize 为 ? Get(obj, "size")。
  3. 令 numberSize 为 ? ToNumber(rawSize)。
  4. 注:如果 rawSize 是 undefined,则 numberSize 将是 NaN。
  5. 如果 numberSize 是 NaN,则抛出 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 )

抽象操作 SetDataHas,接收参数 setData (列表 (元素:(ECMAScript 语言值 或 empty))) 和 value (ECMAScript 语言值);返回值:Boolean。 调用时执行以下步骤:

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

24.2.1.4 SetDataIndex ( setData, value )

抽象操作 SetDataIndex,接收参数 setData (列表 (元素:(ECMAScript 语言值 或 empty))) 和 value (ECMAScript 语言值);返回值:(非负整数 或 not-found)。 调用时执行以下步骤:

  1. 将 value 设置为 CanonicalizeKeyedCollectionKey(value)。
  2. 令 size 为 setData 中的元素数量。
  3. 令 index 为 0。
  4. 当 index < size 时,重复执行,
    1. 令 element 为 setData[index]。
    2. 如果 element 不是 empty 且 element 是 value,则
      1. 返回 index。
    3. 将 index 设置为 index + 1。
  5. 返回 not-found。

24.2.1.5 SetDataSize ( setData )

抽象操作 SetDataSize,接收参数 setData (列表 (元素:(ECMAScript 语言值 或 empty)));返回值:非负整数。 调用时执行以下步骤:

  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. 如果 iterable 是 undefined 或 null,则返回 set。
  5. 令 adder 为 ? Get(set, "add")。
  6. 如果 IsCallable(adder) 是 false,则抛出 TypeError 异常。
  7. 令 iteratorRecord 为 ? GetIterator(iterable, sync)。
  8. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则返回 set。
    3. 令 status 为 Completion(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 value。

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

注

创建派生集合对象的方法应调用 %Symbol.species% 来确定用于创建派生对象的构造函数。子类构造函数可以覆盖 %Symbol.species% 以更改默认构造函数的指定。

24.2.4 Set 原型对象的属性

Set 原型对象:

24.2.4.1 Set.prototype.add ( value )

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

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

24.2.4.2 Set.prototype.clear ( )

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

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

会保留现有的 [[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. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 将 value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. 对 set.[[SetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 empty 且 SameValue(entry, value) 是 true,则
      1. 将 set.[[SetData]] 中值为 entry 的元素替换为值为 empty 的元素。
      2. 返回 true。
  5. 返回 false。
注

值 empty 用作规范机制,以指示某个条目已被删除。实际实现可以采取其他操作,例如从内部数据结构中物理删除该条目。

24.2.4.5 Set.prototype.difference ( other )

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

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 otherRecord 为 ? GetSetRecord(other)。
  4. 令 resultSetData 为 set.[[SetData]] 的副本。
  5. 如果 SetDataSize(set.[[SetData]]) ≤ otherRecord.[[Size]],则
    1. 令 thisSize 为 set.[[SetData]] 中的元素数量。
    2. 令 index 为 0。
    3. 当 index < thisSize 时,重复执行,
      1. 令 entry 为 resultSetData[index]。
      2. 如果 entry 不是 empty,则
        1. 令 inOther 为 ToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
        2. 如果 inOther 是 true,则
          1. 将 resultSetData[index] 设置为 empty。
      3. 将 index 设置为 index + 1。
  6. 否则,
    1. 令 keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
    2. 令 next 为 not-started。
    3. 当 next 不是 done 时,重复执行,
      1. 将 next 设置为 ? IteratorStepValue(keysIterator)。
      2. 如果 next 不是 done,则
        1. 将 next 设置为 CanonicalizeKeyedCollectionKey(next)。
        2. 令 valueIndex 为 SetDataIndex(resultSetData, next)。
        3. 如果 valueIndex 不是 not-found,则
          1. 将 resultSetData[valueIndex] 设置为 empty。
  7. 令 result 为 OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  8. 将 result.[[SetData]] 设置为 resultSetData。
  9. 返回 result。

24.2.4.6 Set.prototype.entries ( )

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

  1. 令 set 为 this value。
  2. 返回 ? CreateSetIterator(set, key+value)。
注

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

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

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

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

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

如果提供了 thisArg 参数,则每次调用 callback 时都会将其用作 this value。如果未提供,则改用 undefined。

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

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

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

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

24.2.4.8 Set.prototype.has ( value )

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

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 将 value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. 对 set.[[SetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 empty 且 SameValue(entry, value) 是 true,则返回 true。
  5. 返回 false。

24.2.4.9 Set.prototype.intersection ( other )

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

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 otherRecord 为 ? GetSetRecord(other)。
  4. 令 resultSetData 为新的空 List。
  5. 如果 SetDataSize(set.[[SetData]]) ≤ otherRecord.[[Size]],则
    1. 令 thisSize 为 set.[[SetData]] 中的元素数量。
    2. 令 index 为 0。
    3. 当 index < thisSize 时,重复执行,
      1. 令 entry 为 set.[[SetData]][index]。
      2. 将 index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. 令 inOther 为 ToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
        2. 如果 inOther 是 true,则
          1. 注:先前对 otherRecord.[[Has]] 的调用可能会删除并重新添加 set.[[SetData]] 的某个元素,这可能导致同一个元素在此次迭代期间被访问两次。
          2. 如果 SetDataHas(resultSetData, entry) 是 false,则
            1. 将 entry 追加到 resultSetData。
        3. 注:在执行 otherRecord.[[Has]] 期间,set.[[SetData]] 中的元素数量可能已经增加。
        4. 将 thisSize 设置为 set.[[SetData]] 中的元素数量。
  6. 否则,
    1. 令 keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
    2. 令 next 为 not-started。
    3. 当 next 不是 done 时,重复执行,
      1. 将 next 设置为 ? IteratorStepValue(keysIterator)。
      2. 如果 next 不是 done,则
        1. 将 next 设置为 CanonicalizeKeyedCollectionKey(next)。
        2. 令 inThis 为 SetDataHas(set.[[SetData]], next)。
        3. 如果 inThis 是 true,则
          1. 注:由于 other 是任意对象,其 "keys" 迭代器可能会多次生成相同的值。
          2. 如果 SetDataHas(resultSetData, next) 是 false,则
            1. 将 next 追加到 resultSetData。
  7. 令 result 为 OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  8. 将 result.[[SetData]] 设置为 resultSetData。
  9. 返回 result。

24.2.4.10 Set.prototype.isDisjointFrom ( other )

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

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 otherRecord 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) ≤ otherRecord.[[Size]],则
    1. 令 thisSize 为 set.[[SetData]] 中的元素数量。
    2. 令 index 为 0。
    3. 当 index < thisSize 时,重复执行,
      1. 令 entry 为 set.[[SetData]][index]。
      2. 将 index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. 令 inOther 为 ToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
        2. 如果 inOther 是 true,则返回 false。
        3. 注:在执行 otherRecord.[[Has]] 期间,set.[[SetData]] 中的元素数量可能已经增加。
        4. 将 thisSize 设置为 set.[[SetData]] 中的元素数量。
  5. 否则,
    1. 令 keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
    2. 令 next 为 not-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. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 otherRecord 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) > otherRecord.[[Size]],则返回 false。
  5. 令 thisSize 为 set.[[SetData]] 中的元素数量。
  6. 令 index 为 0。
  7. 当 index < thisSize 时,重复执行,
    1. 令 entry 为 set.[[SetData]][index]。
    2. 将 index 设置为 index + 1。
    3. 如果 entry 不是 empty,则
      1. 令 inOther 为 ToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
      2. 如果 inOther 是 false,则返回 false。
      3. 注:在执行 otherRecord.[[Has]] 期间,set.[[SetData]] 中的元素数量可能已经增加。
      4. 将 thisSize 设置为 set.[[SetData]] 中的元素数量。
  8. 返回 true。

24.2.4.12 Set.prototype.isSupersetOf ( other )

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

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 otherRecord 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) < otherRecord.[[Size]],则返回 false。
  5. 令 keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
  6. 令 next 为 not-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" 属性的初始值是 24.2.4.17 中定义的 %Set.prototype.values%。

注

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

24.2.4.14 get Set.prototype.size

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

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 size 为 SetDataSize(set.[[SetData]])。
  4. 返回 𝔽(size)。

24.2.4.15 Set.prototype.symmetricDifference ( other )

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

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 otherRecord 为 ? GetSetRecord(other)。
  4. 令 keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
  5. 令 resultSetData 为 set.[[SetData]] 的副本。
  6. 令 next 为 not-started。
  7. 当 next 不是 done 时,重复执行,
    1. 将 next 设置为 ? IteratorStepValue(keysIterator)。
    2. 如果 next 不是 done,则
      1. 将 next 设置为 CanonicalizeKeyedCollectionKey(next)。
      2. 令 resultIndex 为 SetDataIndex(resultSetData, next)。
      3. 如果 resultIndex 是 not-found,则令 alreadyInResult 为 false;否则令 alreadyInResult 为 true。
      4. 如果 SetDataHas(set.[[SetData]], next) 是 true,则
        1. 如果 alreadyInResult 是 true,则将 resultSetData[resultIndex] 设置为 empty。
      5. 否则,
        1. 如果 alreadyInResult 是 false,则将 next 追加到 resultSetData。
  8. 令 result 为 OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  9. 将 result.[[SetData]] 设置为 resultSetData。
  10. 返回 result。

24.2.4.16 Set.prototype.union ( other )

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

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

24.2.4.17 Set.prototype.values ( )

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

  1. 令 set 为 this value。
  2. 返回 ? CreateSetIterator(set, value)。

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

%Symbol.iterator% 属性的初始值是 24.2.4.17 中定义的 %Set.prototype.values%。

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 迭代器对象

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

24.2.6.1 CreateSetIterator ( set, kind )

抽象操作 CreateSetIterator,接收参数 set (ECMAScript 语言值) 和 kind ((key+value 或 value));返回值:(正常完成 (值:Generator) 或 抛出完成)。 它用于为返回此类迭代器的 Set 方法创建迭代器对象。 调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(set, [[SetData]])。
  2. 令 closure 为不带参数的新 Abstract Closure,它捕获 set 和 kind,并在被调用时执行以下步骤:
    1. 令 index 为 0。
    2. 令 entries 为 set.[[SetData]]。
    3. 令 entriesCount 为 entries 中的元素数量。
    4. 当 index < entriesCount 时,重复执行,
      1. 令 entry 为 entries[index]。
      2. 将 index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. 如果 kind 是 key+value,则
          1. 令 result 为 CreateArrayFromList(« entry, entry »)。
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(result, false))。
        2. 否则,
          1. 断言:kind 是 value。
          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 是键/值对的集合,其中键是对象和/或符号,而值可以是任意 ECMAScript 语言值。可以查询 WeakMap 是否包含具有特定键的键/值对,但没有提供枚举其作为键保存的值的机制。在某些条件下,不再存活的值会从 WeakMap 键中移除,如 9.9.3 所述。

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

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

注

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. 如果 iterable 是 undefined 或 null,则返回 map。
  5. 令 adder 为 ? Get(map, "set")。
  6. 如果 IsCallable(adder) 是 false,则抛出 TypeError 异常。
  7. 返回 ? AddEntriesFromIterable(map, iterable, adder)。
注

如果存在参数 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. 令 weakMap 为 this value。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则返回 false。
  4. 对 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则
      1. 将 entry.[[Key]] 设置为 empty。
      2. 将 entry.[[Value]] 设置为 empty。
      3. 返回 true。
  5. 返回 false。
注

值 empty 用作规范机制,以指示某个条目已被删除。实际实现可以采取其他操作,例如从内部数据结构中物理删除该条目。

24.3.3.3 WeakMap.prototype.get ( key )

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

  1. 令 weakMap 为 this value。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则返回 undefined。
  4. 对 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]。
  5. 返回 undefined。

24.3.3.4 WeakMap.prototype.getOrInsert ( key, value )

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

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

24.3.3.5 WeakMap.prototype.getOrInsertComputed ( key, callback )

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

  1. 令 weakMap 为 this value。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则抛出 TypeError 异常。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. 对 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(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]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则
      1. 将 entry.[[Value]] 设置为 value。
      2. 返回 value。
  9. 令 entry 为 Record { [[Key]]: key, [[Value]]: value }。
  10. 将 entry 追加到 weakMap.[[WeakMapData]]。
  11. 返回 value。

24.3.3.6 WeakMap.prototype.has ( key )

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

  1. 令 weakMap 为 this value。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则返回 false。
  4. 对 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则返回 true。
  5. 返回 false。

24.3.3.7 WeakMap.prototype.set ( key, value )

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

  1. 令 weakMap 为 this value。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则抛出 TypeError 异常。
  4. 对 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则
      1. 将 entry.[[Value]] 设置为 value。
      2. 返回 weakMap。
  5. 令 entry 为 Record { [[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 所要求的可观察语义。它并不旨在作为可行的实现模型。

注

参见 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. 如果 iterable 是 undefined 或 null,则返回 set。
  5. 令 adder 为 ? Get(set, "add")。
  6. 如果 IsCallable(adder) 是 false,则抛出 TypeError 异常。
  7. 令 iteratorRecord 为 ? GetIterator(iterable, sync)。
  8. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则返回 set。
    3. 令 status 为 Completion(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. 令 weakSet 为 this value。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,则抛出 TypeError 异常。
  4. 对 weakSet.[[WeakSetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 empty 且 SameValue(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. 令 weakSet 为 this value。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,则返回 false。
  4. 对 weakSet.[[WeakSetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 empty 且 SameValue(entry, value) 是 true,则
      1. 将 weakSet.[[WeakSetData]] 中值为 entry 的元素替换为值为 empty 的元素。
      2. 返回 true。
  5. 返回 false。
注

值 empty 用作规范机制,以指示某个条目已被删除。实际实现可以采取其他操作,例如从内部数据结构中物理删除该条目。

24.4.3.4 WeakSet.prototype.has ( value )

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

  1. 令 weakSet 为 this value。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,则返回 false。
  4. 对 weakSet.[[WeakSetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 empty 且 SameValue(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 )

抽象操作 CanonicalizeKeyedCollectionKey,接收参数 key (ECMAScript 语言值);返回值:ECMAScript 语言值。 调用时执行以下步骤:

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