24 键控集合(Keyed Collections)

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% 方法的对象,该迭代器返回的每个值是一个长度为 2 的类数组对象,其第一个元素用作 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 要么是包含一个 ECMAScript 语言值正常完成要么是抛出完成. 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. kCompletion(Get(next, "0" ))。
    5. IfAbruptCloseIterator(k, iteratorRecord)。
    6. vCompletion(Get(next, "1" ))。
    7. IfAbruptCloseIterator(v, iteratorRecord)。
    8. statusCompletion(Call(adder, target, « k, v »))。
    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]] } g
    1. elementsCreateArrayFromList(g.[[Elements]])。
    2. entry 为记录 { [[Key]]: g.[[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. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. M.[[MapData]] 中每个 Record { [[Key]], [[Value]] } p
    1. p.[[Key]] 设为 empty
    2. p.[[Value]] 设为 empty
  4. 返回 undefined
Note

保留现有的 [[MapData]] List,是因为可能存在已经在该 List 中迭代到一半的 Map 迭代器对象。

24.1.3.2 Map.prototype.constructor

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

24.1.3.3 Map.prototype.delete ( key )

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

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. key 设为 CanonicalizeKeyedCollectionKey(key)。
  4. M.[[MapData]] 中每个 Record { [[Key]], [[Value]] } p
    1. 如果 p.[[Key]] 不是 emptySameValue(p.[[Key]], key) 为 true,则
      1. p.[[Key]] 设为 empty
      2. p.[[Value]] 设为 empty
      3. 返回 true
  5. 返回 false
Note

empty 用作规范设备以指示一个条目已被删除。实际实现可采取其它操作,如在内部数据结构中物理移除此条目。

24.1.3.4 Map.prototype.entries ( )

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

  1. Mthis 值。
  2. 返回 ? CreateMapIterator(M, key+value)。

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

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

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. entriesM.[[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]], M »)。
      2. 注:在执行 callback 期间 entries 中元素数量可能增加。
      3. numEntries 设为 entries 中元素的数量。
  8. 返回 undefined
Note

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

如果提供 thisArg,它将在每次调用 callback 时用作 this 值;否则使用 undefined

callback 以三个参数调用:条目的值、条目的键以及被遍历的 Map。

forEach 不直接修改其被调用的对象,但该对象可在 callback 内被修改。Map 的 [[MapData]] 中的每个条目只访问一次。调用开始后新增的键会被访问。一个键如果在访问后被删除然后在调用结束前又被重新加入会被再次访问。调用开始后删除且尚未访问的键不会被访问,除非它在调用结束前再次添加。

24.1.3.6 Map.prototype.get ( key )

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

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. key 设为 CanonicalizeKeyedCollectionKey(key)。
  4. M.[[MapData]] 中每个 Record { [[Key]], [[Value]] } p
    1. 如果 p.[[Key]] 不是 emptySameValue(p.[[Key]], key) 为 true,返回 p.[[Value]]
  5. 返回 undefined

24.1.3.7 Map.prototype.has ( key )

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

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. key 设为 CanonicalizeKeyedCollectionKey(key)。
  4. M.[[MapData]] 中每个 Record { [[Key]], [[Value]] } p
    1. 如果 p.[[Key]] 不是 emptySameValue(p.[[Key]], key) 为 true,返回 true
  5. 返回 false

24.1.3.8 Map.prototype.keys ( )

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

  1. Mthis 值。
  2. 返回 ? CreateMapIterator(M, key)。

24.1.3.9 Map.prototype.set ( key, value )

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

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. key 设为 CanonicalizeKeyedCollectionKey(key)。
  4. M.[[MapData]] 中每个 Record { [[Key]], [[Value]] } p
    1. 如果 p.[[Key]] 不是 emptySameValue(p.[[Key]], key) 为 true,则
      1. p.[[Value]] 设为 value
      2. 返回 M
  5. p 为记录 { [[Key]]: key, [[Value]]: value }。
  6. p 追加到 M.[[MapData]]
  7. 返回 M

24.1.3.10 get Map.prototype.size

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

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. count 为 0。
  4. M.[[MapData]] 中每个 Record { [[Key]], [[Value]] } p
    1. 如果 p.[[Key]] 不是 empty,将 count 设为 count + 1。
  5. 返回 𝔽(count)。

24.1.3.11 Map.prototype.values ( )

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

  1. Mthis 值。
  2. 返回 ? CreateMapIterator(M, value)。

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

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

24.1.3.13 Map.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串 "Map"

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

24.1.4 Map 实例的属性

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

24.1.5 Map 迭代器对象

Map Iterator 是一个表示对某个特定 Map 实例对象的特定迭代的对象。没有命名的 Map 迭代器构造函数。相反,通过调用某些 Map 实例对象的方法创建 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 一个包含 Generator 的正常完成或抛出完成. 用于为返回此类迭代器的 Map 方法创建迭代器对象。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(map, [[MapData]])。
  2. closure 为一个无参数的新抽象闭包,捕获 mapkind 并在调用时执行:
    1. entriesmap.[[MapData]]
    2. index 为 0。
    3. numEntriesentries 中元素的数量。
    4. index < numEntries 重复,
      1. eentries[index]。
      2. index 设为 index + 1。
      3. 如果 e.[[Key]] 不是 empty,则
        1. 如果 kindkey,则
          1. resulte.[[Key]]
        2. 否则如果 kindvalue,则
          1. resulte.[[Value]]
        3. 否则,
          1. 断言:kindkey+value
          2. resultCreateArrayFromListe.[[Key]], e.[[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% 对象:

  • 具有所有 Map 迭代器对象继承的属性。
  • 是一个普通对象
  • 有一个 [[Prototype]] 内部槽,其值为 %Iterator.prototype%
  • 具有以下属性:

24.1.5.2.1 %MapIteratorPrototype%.next ( )

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

24.1.5.2.2 %MapIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串 "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 记录

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

Set 记录具有 Table 74 中列出的字段。

Table 74: Set 记录字段
字段名 取值 含义
[[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 一个包含 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 (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 一个非负整数或 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 (a List of either ECMAScript language values or empty) 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. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]])。
  3. value 设为 CanonicalizeKeyedCollectionKey(value)。
  4. S.[[SetData]] 中每个元素 e
    1. 如果 e 不是 emptySameValue(e, value) 为 true,则
      1. 返回 S
  5. value 追加到 S.[[SetData]]
  6. 返回 S

24.2.4.2 Set.prototype.clear ( )

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

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]])。
  3. S.[[SetData]] 中每个元素 e
    1. 用值为 empty 的元素替换 S.[[SetData]] 中值为 e 的元素。
  4. 返回 undefined
Note

保留现有 [[SetData]] List,因为可能存在已经在该 List 中迭代到一半的 Set 迭代器对象。

24.2.4.3 Set.prototype.constructor

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

24.2.4.4 Set.prototype.delete ( value )

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

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

empty 用作规范设备指示条目已删除。实际实现可以物理删除该条目等。

24.2.4.5 Set.prototype.difference ( other )

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

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. resultSetDataO.[[SetData]] 的一个拷贝。
  5. 如果 SetDataSize(O.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeO.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. index < thisSize 重复,
      1. eresultSetData[index]。
      2. 如果 e 不是 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « e »))。
        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. Sthis 值。
  2. 返回 ? CreateSetIterator(S, key+value)。
Note

在迭代语义上,Set 类似于每个条目键和值相同的 Map。

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

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

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

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

如果提供 thisArg,它作为每次调用 callbackthis 值;否则使用 undefined

callback 以三个参数调用:前两个参数是 Set 中的一个值(相同的值传两次),第三个参数是被遍历的 Set 对象。

callback 传递三个参数是为了与 Map 和 Array 的 forEach 回调函数保持一致;在 Set 中每个值同时被视为键和值。

forEach 不直接修改其被调用的对象,但对象可在 callback 中被修改。

每个值通常只访问一次;但如果某值在被访问后被删除并在调用结束前重新加入,会被再次访问。调用开始后删除且尚未访问的值不会被访问,除非在调用结束前再次添加。调用开始后新增的值会被访问。

24.2.4.8 Set.prototype.has ( value )

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

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]])。
  3. value 设为 CanonicalizeKeyedCollectionKey(value)。
  4. S.[[SetData]] 中每个元素 e
    1. 如果 e 不是 emptySameValue(e, value) 为 true,返回 true
  5. 返回 false

24.2.4.9 Set.prototype.intersection ( other )

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

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. resultSetData 为一个新的空 List
  5. 如果 SetDataSize(O.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeO.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. index < thisSize 重复,
      1. eO.[[SetData]][index]。
      2. index 设为 index + 1。
      3. 如果 e 不是 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « e »))。
        2. 如果 inOthertrue,则
          1. 注:早先对 otherRec.[[Has]] 的调用可能移除并重新添加 O.[[SetData]] 的元素,导致同一元素在本次迭代中被访问两次。
          2. 如果 SetDataHas(resultSetData, e) 为 false,则
            1. e 追加到 resultSetData
        3. 注:执行 otherRec.[[Has]] 期间 O.[[SetData]] 中元素数量可能增加。
        4. thisSize 设为 O.[[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(O.[[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. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(O.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeO.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. index < thisSize 重复,
      1. eO.[[SetData]][index]。
      2. index 设为 index + 1。
      3. 如果 e 不是 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « e »))。
        2. 如果 inOthertrue,返回 false
        3. 注:执行 otherRec.[[Has]] 期间 O.[[SetData]] 中元素数量可能增加。
        4. thisSize 设为 O.[[SetData]] 中元素的数量。
  5. 否则,
    1. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
    2. nextnot-started
    3. next 不是 done 重复,
      1. next 设为 ? IteratorStepValue(keysIter)。
      2. 如果 next 不是 done,则
        1. 如果 SetDataHas(O.[[SetData]], next) 为 true,则
          1. 执行 ? IteratorClose(keysIter, NormalCompletion(unused))。
          2. 返回 false
  6. 返回 true

24.2.4.11 Set.prototype.isSubsetOf ( other )

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

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

24.2.4.12 Set.prototype.isSupersetOf ( other )

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

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(O.[[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(O.[[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. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]])。
  3. sizeSetDataSize(S.[[SetData]])。
  4. 返回 𝔽(size)。

24.2.4.15 Set.prototype.symmetricDifference ( other )

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

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  5. resultSetDataO.[[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;否则令其为 true
      4. 如果 SetDataHas(O.[[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. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  5. resultSetDataO.[[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. Sthis 值。
  2. 返回 ? CreateSetIterator(S, 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% 属性的初始值是字符串 "Set"

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

24.2.5 Set 实例的属性

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

24.2.6 Set 迭代器对象

Set Iterator 是一个普通对象,结构如下,表示对某个特定 Set 实例对象的特定迭代。没有命名的 Set 迭代器构造函数。相反,通过调用某些 Set 实例对象的方法创建 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 一个包含 Generator 的正常完成或抛出完成. 用于为返回此类迭代器的 Set 方法创建迭代器对象。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(set, [[SetData]])。
  2. closure 为一个无参数的新抽象闭包,捕获 setkind 并在调用时执行:
    1. index 为 0。
    2. entriesset.[[SetData]]
    3. numEntriesentries 中元素的数量。
    4. index < numEntries 重复,
      1. eentries[index]。
      2. index 设为 index + 1。
      3. 如果 e 不是 empty,则
        1. 如果 kindkey+value,则
          1. resultCreateArrayFromListe, e »)。
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(result, false))。
        2. 否则,
          1. 断言:kindvalue
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(e, false))。
        3. 注:在 GeneratorYield 暂停本抽象操作执行期间,entries 中元素数量可能增加。
        4. numEntries 设为 entries 中元素的数量。
    5. 返回 NormalCompletion(unused)。
  3. 返回 CreateIteratorFromClosure(closure, "%SetIteratorPrototype%", %SetIteratorPrototype%)。

24.2.6.2 %SetIteratorPrototype% 对象

%SetIteratorPrototype% 对象:

  • 具有所有 Set 迭代器对象继承的属性。
  • 是一个普通对象
  • 有一个 [[Prototype]] 内部槽,其值为 %Iterator.prototype%
  • 具有以下属性:

24.2.6.2.1 %SetIteratorPrototype%.next ( )

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

24.2.6.2.2 %SetIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串 "Set Iterator"

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

24.3 WeakMap 对象

WeakMap 是键/值对的集合,其中键是对象和/或符号,值可以是任意 ECMAScript 语言值。可以查询 WeakMap 是否包含具有特定键的键/值对,但没有枚举其持有键的机制。在特定条件下,非存活的值会作为 WeakMap 的键被移除,详见 9.9.3

实现可以在 WeakMap 的键/值对变得不可访问与其被移除之间施加任意决定的延迟。若该延迟对 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. 载于 Proceedings of the 12th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications (OOPSLA '97), A. Michael Berman (编). 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. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 为 false,返回 false
  4. M.[[WeakMapData]] 中每个 Record { [[Key]], [[Value]] } p
    1. 如果 p.[[Key]] 不是 emptySameValue(p.[[Key]], key) 为 true,则
      1. p.[[Key]] 设为 empty
      2. p.[[Value]] 设为 empty
      3. 返回 true
  5. 返回 false
Note

empty 用作规范设备指示条目已删除。实际实现可能物理移除该条目。

24.3.3.3 WeakMap.prototype.get ( key )

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

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 为 false,返回 undefined
  4. M.[[WeakMapData]] 中每个 Record { [[Key]], [[Value]] } p
    1. 如果 p.[[Key]] 不是 emptySameValue(p.[[Key]], key) 为 true,返回 p.[[Value]]
  5. 返回 undefined

24.3.3.4 WeakMap.prototype.has ( key )

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

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 为 false,返回 false
  4. M.[[WeakMapData]] 中每个 Record { [[Key]], [[Value]] } p
    1. 如果 p.[[Key]] 不是 emptySameValue(p.[[Key]], key) 为 true,返回 true
  5. 返回 false

24.3.3.5 WeakMap.prototype.set ( key, value )

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

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 为 false,抛出 TypeError 异常。
  4. M.[[WeakMapData]] 中每个 Record { [[Key]], [[Value]] } p
    1. 如果 p.[[Key]] 不是 emptySameValue(p.[[Key]], key) 为 true,则
      1. p.[[Value]] 设为 value
      2. 返回 M
  5. p 为记录 { [[Key]]: key, [[Value]]: value }。
  6. p 追加到 M.[[WeakMapData]]
  7. 返回 M

24.3.3.6 WeakMap.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串 "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 中的一个值变得不可访问与其被移除之间施加任意决定的延迟。若该延迟对 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. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 为 false,抛出 TypeError 异常。
  4. S.[[WeakSetData]] 中每个元素 e
    1. 如果 e 不是 emptySameValue(e, value) 为 true,则
      1. 返回 S
  5. value 追加到 S.[[WeakSetData]]
  6. 返回 S

24.4.3.2 WeakSet.prototype.constructor

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

24.4.3.3 WeakSet.prototype.delete ( value )

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

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

empty 用作规范设备指示条目已删除。实际实现可能物理移除该条目。

24.4.3.4 WeakSet.prototype.has ( value )

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

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 为 false,返回 false
  4. S.[[WeakSetData]] 中每个元素 e
    1. 如果 e 不是 emptySameValue(e, value) 为 true,返回 true
  5. 返回 false

24.4.3.5 WeakSet.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串 "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