页面模式偏好

7 抽象操作

这些操作不是 ECMAScript 语言的一部分;它们在此定义,仅用于帮助规定 ECMAScript 语言的语义。其他更专门的抽象操作在本规范各处定义。

7.1 类型转换

ECMAScript 语言会根据需要隐式执行自动类型转换。为了阐明某些构造的语义,定义一组转换抽象操作很有用。转换抽象操作是多态的;它们可以接受任何 ECMAScript 语言类型的值。但这些操作不使用任何其他规范类型。

BigInt 类型在 ECMAScript 语言中没有隐式转换;程序员必须显式调用 BigInt 才能将其他类型的值转换为 BigInt。

7.1.1 ToPrimitive ( input [ , preferredType ] )

抽象操作 ToPrimitive,接收参数 input (ECMAScript 语言值)和可选参数 preferredType ((string 或 number));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它将其 input 参数转换为非 Object 类型。如果一个对象能够转换为多种原始类型,则可以使用可选提示 preferredType 来优先选择该类型。 调用时执行以下步骤:

  1. 如果 input 是 Object,则
    1. 令 exoticToPrimitive 为 ? GetMethod(input, %Symbol.toPrimitive%)。
    2. 如果 exoticToPrimitive 不是 undefined,则
      1. 如果不存在 preferredType,则
        1. 令 hint 为 "default"。
      2. 否则如果 preferredType 是 string,则
        1. 令 hint 为 "string"。
      3. 否则,
        1. 断言:preferredType 是 number。
        2. 令 hint 为 "number"。
      4. 令 result 为 ? Call(exoticToPrimitive, input, « hint »)。
      5. 如果 result 不是 Object,则返回 result。
      6. 抛出 TypeError 异常。
    3. 如果不存在 preferredType,则将 preferredType 设置为 number。
    4. 返回 ? OrdinaryToPrimitive(input, preferredType)。
  2. 返回 input。
注

当调用 ToPrimitive 时没有提供提示,它通常表现得如同提示为 number。但是,对象可以通过定义 %Symbol.toPrimitive% 方法来覆盖此行为。在本规范定义的对象中,只有 Date(参见 21.4.4.45)和 Symbol 对象(参见 20.4.3.5)会覆盖默认的 ToPrimitive 行为。Date 将缺少提示的情况视为提示为 string。

7.1.1.1 OrdinaryToPrimitive ( obj, hint )

抽象操作 OrdinaryToPrimitive,接收参数 obj (Object) 和 hint ((string 或 number));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 hint 是 string,则
    1. 令 methodNames 为 « "toString", "valueOf" »。
  2. 否则,
    1. 令 methodNames 为 « "valueOf", "toString" »。
  3. 对 methodNames 的每个元素 name,执行
    1. 令 method 为 ? Get(obj, name)。
    2. 如果 IsCallable(method) 是 true,则
      1. 令 result 为 ? Call(method, obj)。
      2. 如果 result 不是 Object,则返回 result。
  4. 抛出 TypeError 异常。

7.1.2 ToBoolean ( arg )

抽象操作 ToBoolean,接收参数 arg (ECMAScript 语言值);返回值:Boolean。 它将 arg 转换为 Boolean 类型的值。 调用时执行以下步骤:

  1. 如果 arg 是 Boolean,则返回 arg。
  2. 如果 arg 是 undefined、null、+0𝔽、-0𝔽、NaN、0ℤ 或空 String 之一,则返回 false。
  3. Normative Optional
    如果宿主是 Web 浏览器或以其他方式支持 [[IsHTMLDDA]] 内部槽,则
    1. 如果 arg 是 Object 且 arg 具有 [[IsHTMLDDA]] 内部槽,则返回 false。
  4. 返回 true。

7.1.3 ToNumeric ( arg )

抽象操作 ToNumeric,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:(Number 或 BigInt)) 或 抛出完成)。 它返回转换为 Number 或 BigInt 后的 arg。 调用时执行以下步骤:

  1. 令 primitiveValue 为 ? ToPrimitive(arg, number)。
  2. 如果 primitiveValue 是 BigInt,则返回 primitiveValue。
  3. 返回 ? ToNumber(primitiveValue)。

7.1.4 ToNumber ( arg )

抽象操作 ToNumber,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:Number) 或 抛出完成)。 它将 arg 转换为 Number 类型的值。 调用时执行以下步骤:

  1. 如果 arg 是 Number,则返回 arg。
  2. 如果 arg 是 Symbol 或 BigInt,则抛出 TypeError 异常。
  3. 如果 arg 是 undefined,则返回 NaN。
  4. 如果 arg 是 null 或 false,则返回 +0𝔽。
  5. 如果 arg 是 true,则返回 1𝔽。
  6. 如果 arg 是 String,则返回 StringToNumber(arg)。
  7. 断言:arg 是 Object。
  8. 令 primitiveValue 为 ? ToPrimitive(arg, number)。
  9. 断言:primitiveValue 不是 Object。
  10. 返回 ? ToNumber(primitiveValue)。

7.1.4.1 应用于 String 类型的 ToNumber

抽象操作 StringToNumber 使用以下文法规定如何将 String 值转换为 Number 值。

语法

StringNumericLiteral ::: StrWhiteSpaceopt StrWhiteSpaceopt StrNumericLiteral StrWhiteSpaceopt StrWhiteSpace ::: StrWhiteSpaceChar StrWhiteSpaceopt StrWhiteSpaceChar ::: WhiteSpace LineTerminator StrNumericLiteral ::: StrDecimalLiteral NonDecimalIntegerLiteral[~Sep] StrDecimalLiteral ::: StrUnsignedDecimalLiteral + StrUnsignedDecimalLiteral - StrUnsignedDecimalLiteral StrUnsignedDecimalLiteral ::: Infinity DecimalDigits[~Sep] . DecimalDigits[~Sep]opt ExponentPart[~Sep]opt . DecimalDigits[~Sep] ExponentPart[~Sep]opt DecimalDigits[~Sep] ExponentPart[~Sep]opt

以上未显式定义的所有文法符号,都采用数值字面量词法文法(12.9.3)中使用的定义

注

应注意 StringNumericLiteral 与 NumericLiteral 的语法之间存在一些差异:

7.1.4.1.1 StringToNumber ( string )

抽象操作 StringToNumber,接收参数 string (String);返回值:Number。 调用时执行以下步骤:

  1. 令 literal 为 ParseText(string, StringNumericLiteral)。
  2. 如果 literal 是错误的 List,则返回 NaN。
  3. 返回 literal 的 StringNumericValue。

7.1.4.1.2 Runtime Semantics: StringNumericValue

语法制导操作 StringNumericValue,接收无参数;返回值:Number。

注

将 StringNumericLiteral 转换为 Number 值,在整体上类似于确定 NumericLiteral 的 NumericValue(参见 12.9.3),但某些细节有所不同。

它按以下产生式分别定义:

StringNumericLiteral ::: StrWhiteSpaceopt
  1. 返回 +0𝔽。
StringNumericLiteral ::: StrWhiteSpaceopt StrNumericLiteral StrWhiteSpaceopt
  1. 返回 StrNumericLiteral 的 StringNumericValue。
StrNumericLiteral ::: NonDecimalIntegerLiteral
  1. 返回 𝔽(NonDecimalIntegerLiteral 的 MV)。
StrDecimalLiteral ::: - StrUnsignedDecimalLiteral
  1. 令 a 为 StrUnsignedDecimalLiteral 的 StringNumericValue。
  2. 如果 a 是 +0𝔽,则返回 -0𝔽。
  3. 返回 -a。
StrUnsignedDecimalLiteral ::: Infinity
  1. 返回 +∞𝔽。
StrUnsignedDecimalLiteral ::: DecimalDigits . DecimalDigitsopt ExponentPartopt
  1. 令 a 为第一个 DecimalDigits 的 MV。
  2. 如果存在第二个 DecimalDigits,则
    1. 令 b 为第二个 DecimalDigits 的 MV。
    2. 令 n 为第二个 DecimalDigits 中的码点数。
  3. 否则,
    1. 令 b 为 0。
    2. 令 n 为 0。
  4. 如果存在 ExponentPart,则令 e 为 ExponentPart 的 MV;否则令 e 为 0。
  5. 返回 RoundMVResult((a + (b × 10-n)) × 10e)。
StrUnsignedDecimalLiteral ::: . DecimalDigits ExponentPartopt
  1. 令 b 为 DecimalDigits 的 MV。
  2. 如果存在 ExponentPart,则令 e 为 ExponentPart 的 MV;否则令 e 为 0。
  3. 令 n 为 DecimalDigits 中的码点数。
  4. 返回 RoundMVResult(b × 10e - n)。
StrUnsignedDecimalLiteral ::: DecimalDigits ExponentPartopt
  1. 令 a 为 DecimalDigits 的 MV。
  2. 如果存在 ExponentPart,则令 e 为 ExponentPart 的 MV;否则令 e 为 0。
  3. 返回 RoundMVResult(a × 10e)。

7.1.4.1.3 RoundMVResult ( n )

抽象操作 RoundMVResult,接收参数 n (数学值);返回值:Number。 它以实现定义的方式将 n 转换为 Number。对于此抽象操作,如果一个数字不为零,或者其左侧存在非零数字且其右侧也存在非零数字,则该数字是有效数字。对于此抽象操作,一个数学值表示形式“所表示的数学值”是一个数学值“十进制表示”的逆操作。 调用时执行以下步骤:

  1. 如果 n 的十进制表示具有 20 个或更少的有效数字,则返回 𝔽(n)。
  2. 令 option1 为这样一个结果所表示的数学值:将 n 的十进制表示中第 20 个之后的每个有效数字替换为数字 0。
  3. 令 option2 为这样一个结果所表示的数学值:将 n 的十进制表示中第 20 个之后的每个有效数字替换为数字 0,然后在第 20 位将其递增(必要时进行进位)。
  4. 令 chosen 为实现定义地从 option1 或 option2 中选择的一个值。
  5. 返回 𝔽(chosen)。

7.1.5 ToIntegerOrInfinity ( arg )

抽象操作 ToIntegerOrInfinity,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:(整数、+∞ 或 -∞)) 或 抛出完成)。 它将 arg 转换为表示其 Number 值、且小数部分被截断的整数;如果该 Number 值为无穷,则转换为 +∞ 或 -∞。 调用时执行以下步骤:

  1. 令 number 为 ? ToNumber(arg)。
  2. 如果 number 是 NaN、+0𝔽 或 -0𝔽 之一,则返回 0。
  3. 如果 number 是 +∞𝔽,则返回 +∞。
  4. 如果 number 是 -∞𝔽,则返回 -∞。
  5. 返回 truncate(ℝ(number))。
注
对于 x 的任何值,𝔽(ToIntegerOrInfinity(x)) 都不会返回 -0𝔽。小数部分的截断是在将 x 转换为数学值之后执行的。

7.1.6 SnapToInteger ( arg, nonIntHandling [ , minimum [ , maximum ] ] )

抽象操作 SnapToInteger,接收参数 arg (ECMAScript 语言值) 和 nonIntHandling ((reject 或 truncate))和可选参数 minimum (整数) 和 maximum (整数);返回值:(正常完成 (值:整数) 或 抛出完成)。 它将 arg 转换为表示其 Number 值的整数;拒绝非有限值,并通过拒绝或截断来处理有限的非整数值,还可以选择施加包含端点的约束边界。 调用时执行以下步骤:

  1. 令 number 为 ? ToNumber(arg)。
  2. 如果 number 是 NaN、+∞𝔽 或 -∞𝔽 之一,则抛出 RangeError 异常。
  3. 令 mv 为 ℝ(number)。
  4. 如果 nonIntHandling 是 truncate,则将 mv 设置为 truncate(mv)。
  5. 如果 mv 不是整数,则抛出 RangeError 异常。
  6. 如果存在 minimum 且 mv < minimum,则抛出 RangeError 异常。
  7. 如果存在 maximum 且 mv > maximum,则抛出 RangeError 异常。
  8. 返回 mv。

7.1.7 ToFixedSizeInteger ( int, signed, bitWidth )

抽象操作 ToFixedSizeInteger,接收参数 int ((整数、+∞ 或 -∞))、signed ((unsigned 或 signed)) 和 bitWidth (正整数);返回值:整数。 它将 int 映射到 2bitWidth 个整数之一:如果 signed 为 unsigned,范围是从 0 到 2bitWidth - 1 的闭区间;如果 signed 为 signed,范围是从 -2bitWidth - 1 到 2bitWidth - 1 - 1。 调用时执行以下步骤:

  1. 如果 int = +∞ 或 int = -∞,则返回 0。
  2. 令 fixedInt 为 int modulo 2bitWidth。
  3. 注:以下步骤不会改变 fixedInt 的二进制补码表示。
  4. 如果 signed 是 signed 且 fixedInt ≥ 2bitWidth - 1,则将 fixedInt 设置为 fixedInt - 2bitWidth。
  5. 返回 fixedInt。
注

ToFixedSizeInteger 是幂等的:对于任何 ECMAScript 语言值 x,ToFixedSizeInteger(ToFixedSizeInteger(x, signed, bitWidth), signed, bitWidth) 与 ToFixedSizeInteger(x, signed, bitWidth) 相同。实际上,因为 +∞ 和 -∞ 都映射为 0,即使反转 signed,此不变量仍然成立(例如,ToFixedSizeInteger(ToFixedSizeInteger(x, signed, 32), unsigned, 32) 与 ToFixedSizeInteger(x, unsigned, 32) 相同)。

7.1.8 ToInt32 ( arg )

抽象操作 ToInt32,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 转换为从 𝔽(-231) 到 𝔽(231 - 1) 的闭区间中的 232 个整数 Number 值之一,不包括 -0𝔽。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 返回 𝔽(ToFixedSizeInteger(int, signed, 32))。

7.1.9 ToUint32 ( arg )

抽象操作 ToUint32,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 转换为从 +0𝔽 到 𝔽(232 - 1) 的闭区间中的 232 个整数 Number 值之一。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 返回 𝔽(ToFixedSizeInteger(int, unsigned, 32))。

7.1.10 ToInt16 ( arg )

抽象操作 ToInt16,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 转换为从 𝔽(-215) 到 𝔽(215 - 1) 的闭区间中的 216 个整数 Number 值之一,不包括 -0𝔽。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 返回 𝔽(ToFixedSizeInteger(int, signed, 16))。

7.1.11 ToUint16 ( arg )

抽象操作 ToUint16,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 转换为从 +0𝔽 到 𝔽(216 - 1) 的闭区间中的 216 个整数 Number 值之一。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 返回 𝔽(ToFixedSizeInteger(int, unsigned, 16))。

7.1.12 ToInt8 ( arg )

抽象操作 ToInt8,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 转换为从 -128𝔽 到 127𝔽 的闭区间中的 28 个整数 Number 值之一,不包括 -0𝔽。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 返回 𝔽(ToFixedSizeInteger(int, signed, 8))。

7.1.13 ToUint8 ( arg )

抽象操作 ToUint8,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 转换为从 +0𝔽 到 255𝔽 的闭区间中的 28 个整数 Number 值之一。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 返回 𝔽(ToFixedSizeInteger(int, unsigned, 8))。

7.1.14 ToUint8Clamp ( arg )

抽象操作 ToUint8Clamp,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 钳制并舍入为从 +0𝔽 到 255𝔽 的闭区间中的 28 个整数 Number 值之一。 调用时执行以下步骤:

  1. 令 number 为 ? ToNumber(arg)。
  2. 如果 number 是 NaN,则返回 +0𝔽。
  3. 令 mv 为 number 的扩展数学值。
  4. 令 clamped 为将 mv 钳制在 0 和 255 之间的结果。
  5. 令 f 为 floor(clamped)。
  6. 如果 clamped < f + 0.5,则返回 𝔽(f)。
  7. 如果 clamped > f + 0.5,则返回 𝔽(f + 1)。
  8. 如果 f 是偶数,则返回 𝔽(f)。
  9. 返回 𝔽(f + 1)。
注

与大多数其他 ECMAScript 整数转换操作不同,ToUint8Clamp 对非整数值进行舍入,而不是截断。它还使用“舍入到最接近值,恰好一半时舍入到偶数”的平局处理方式,这与 Math.round 使用的“恰好一半时向上舍入”不同。

7.1.15 ToBigInt ( arg )

抽象操作 ToBigInt,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:BigInt) 或 抛出完成)。 它将 arg 转换为 BigInt 值;如果需要从 Number 进行隐式转换,则抛出异常。 调用时执行以下步骤:

  1. 令 primitive 为 ? ToPrimitive(arg, number)。
  2. 返回 表 12 中与 primitive 对应的值。
表 12: BigInt 转换
参数类型 结果
Undefined 抛出 TypeError 异常。
Null 抛出 TypeError 异常。
Boolean 如果 primitive 是 true,则返回 1n;如果 primitive 是 false,则返回 0n。
BigInt 返回 primitive。
Number 抛出 TypeError 异常。
String
  1. 令 n 为 StringToBigInt(primitive)。
  2. 如果 n 是 undefined,则抛出 SyntaxError 异常。
  3. 返回 n。
Symbol 抛出 TypeError 异常。

7.1.16 StringToBigInt ( string )

抽象操作 StringToBigInt,接收参数 string (String);返回值:(BigInt 或 undefined)。 调用时执行以下步骤:

  1. 令 literal 为 ParseText(string, StringIntegerLiteral)。
  2. 如果 literal 是错误的 List,则返回 undefined。
  3. 令 mv 为 literal 的 MV。
  4. 断言:mv 是整数。
  5. 返回 ℤ(mv)。

7.1.16.1 StringIntegerLiteral 文法

StringToBigInt 使用以下文法。

语法

StringIntegerLiteral ::: StrWhiteSpaceopt StrWhiteSpaceopt StrIntegerLiteral StrWhiteSpaceopt StrIntegerLiteral ::: SignedInteger[~Sep] NonDecimalIntegerLiteral[~Sep]

7.1.16.2 Runtime Semantics: MV

7.1.17 ToBigInt64 ( arg )

抽象操作 ToBigInt64,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:BigInt) 或 抛出完成)。 它将 arg 转换为从 ℤ(-263) 到 ℤ(263 - 1) 的闭区间中的 264 个 BigInt 值之一。 调用时执行以下步骤:

  1. 令 int 为 ℝ(? ToBigInt(arg))。
  2. 返回 ℤ(ToFixedSizeInteger(int, signed, 64))。

7.1.18 ToBigUint64 ( arg )

抽象操作 ToBigUint64,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:BigInt) 或 抛出完成)。 它将 arg 转换为从 0ℤ 到 ℤ(264 - 1) 的闭区间中的 264 个 BigInt 值之一。 调用时执行以下步骤:

  1. 令 int 为 ℝ(? ToBigInt(arg))。
  2. 返回 ℤ(ToFixedSizeInteger(int, unsigned, 64))。

7.1.19 ToString ( arg )

抽象操作 ToString,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:String) 或 抛出完成)。 它将 arg 转换为 String 类型的值。 调用时执行以下步骤:

  1. 如果 arg 是 String,则返回 arg。
  2. 如果 arg 是 Symbol,则抛出 TypeError 异常。
  3. 如果 arg 是 undefined,则返回 "undefined"。
  4. 如果 arg 是 null,则返回 "null"。
  5. 如果 arg 是 true,则返回 "true"。
  6. 如果 arg 是 false,则返回 "false"。
  7. 如果 arg 是 Number,则返回 Number::toString(arg, 10)。
  8. 如果 arg 是 BigInt,则返回 BigInt::toString(arg, 10)。
  9. 断言:arg 是 Object。
  10. 令 primitiveValue 为 ? ToPrimitive(arg, string)。
  11. 断言:primitiveValue 不是 Object。
  12. 返回 ? ToString(primitiveValue)。

7.1.20 ToObject ( arg )

抽象操作 ToObject,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:Object) 或 抛出完成)。 它将 arg 转换为 Object 类型的值。 调用时执行以下步骤:

  1. 如果 arg 是 undefined 或 null,则抛出 TypeError 异常。
  2. 如果 arg 是 Boolean,则返回一个新的 Boolean 对象,其 [[BooleanData]] 内部槽设置为 arg。有关 Boolean 对象的描述,请参见 20.3。
  3. 如果 arg 是 Number,则返回一个新的 Number 对象,其 [[NumberData]] 内部槽设置为 arg。有关 Number 对象的描述,请参见 21.1。
  4. 如果 arg 是 String,则返回一个新的 String 对象,其 [[StringData]] 内部槽设置为 arg。有关 String 对象的描述,请参见 22.1。
  5. 如果 arg 是 Symbol,则返回一个新的 Symbol 对象,其 [[SymbolData]] 内部槽设置为 arg。有关 Symbol 对象的描述,请参见 20.4。
  6. 如果 arg 是 BigInt,则返回一个新的 BigInt 对象,其 [[BigIntData]] 内部槽设置为 arg。有关 BigInt 对象的描述,请参见 21.2。
  7. 断言:arg 是 Object。
  8. 返回 arg。

7.1.21 ToPropertyKey ( arg )

抽象操作 ToPropertyKey,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:属性键) 或 抛出完成)。 它将 arg 转换为可用作属性键的值。 调用时执行以下步骤:

  1. 令 key 为 ? ToPrimitive(arg, string)。
  2. 如果 key 是 Symbol,则
    1. 返回 key。
  3. 返回 ! ToString(key)。

7.1.22 ToLength ( arg )

抽象操作 ToLength,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:非负整数 Number) 或 抛出完成)。 它将 arg 钳制并截断为适合用作类数组对象长度的非负整数 Number。 调用时执行以下步骤:

  1. 令 length 为 ? ToIntegerOrInfinity(arg)。
  2. 令 clampedLength 为将 length 钳制在 0 和 253 - 1 之间的结果。
  3. 返回 𝔽(clampedLength)。

7.1.23 CanonicalNumericIndexString ( arg )

抽象操作 CanonicalNumericIndexString,接收参数 arg (String);返回值:(Number 或 undefined)。 如果 arg 是 "-0",或者与某个 Number 值 n 的 ToString(n) 完全匹配,则返回相应的 Number 值。否则返回 undefined。 调用时执行以下步骤:

  1. 如果 arg 是 "-0",则返回 -0𝔽。
  2. 令 n 为 ! ToNumber(arg)。
  3. 如果 ! ToString(n) 是 arg,则返回 n。
  4. 返回 undefined。

规范数值字符串是 CanonicalNumericIndexString 抽象操作不会对其返回 undefined 的任何 String。

7.1.24 ToIndex ( arg )

抽象操作 ToIndex,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:非负整数) 或 抛出完成)。 它将 arg 转换为整数;如果该整数非负并对应于整数索引,则返回该整数。否则抛出异常。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 如果 int 不在从 0 到 253 - 1 的闭区间中,则抛出 RangeError 异常。
  3. 返回 int。

7.1.25 ToAbsoluteIndex ( value, length )

抽象操作 ToAbsoluteIndex,接收参数 value (ECMAScript 语言值) 和 length (非负整数);返回值:(正常完成 (值:(整数、+∞ 或 -∞)) 或 抛出完成)。 它将 value 转换为整数、+∞ 或 -∞,并相对于 length 解释负值。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(value)。
  2. 如果 int 是有限值且 int < 0,则将 int 设置为 length + int。
  3. 返回 int。

7.1.26 ToClampedIndex ( value, length )

抽象操作 ToClampedIndex,接收参数 value (ECMAScript 语言值) 和 length (非负整数);返回值:(正常完成 (值:非负整数) 或 抛出完成)。 它将 value 转换为整数(相对于 length 解释负值),并将结果钳制到从 0 到 length 的闭区间。 调用时执行以下步骤:

  1. 令 index 为 ? ToAbsoluteIndex(value, length)。
  2. 返回将 index 钳制在 0 和 length 之间的结果。

7.2 测试和比较操作

7.2.1 RequireObjectCoercible ( arg )

抽象操作 RequireObjectCoercible,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 如果 arg 是无法使用 ToObject 转换为 Object 的值,则它抛出错误。 调用时执行以下步骤:

  1. 如果 arg 是 undefined 或 null,则抛出 TypeError 异常。
  2. 返回 unused。

7.2.2 IsArray ( arg )

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

  1. 如果 arg 不是 Object,则返回 false。
  2. 如果 arg 是 Array 异质对象,则返回 true。
  3. 如果 arg 是 Proxy 异质对象,则
    1. 执行 ? ValidateNonRevokedProxy(arg)。
    2. 令 proxyTarget 为 arg.[[ProxyTarget]]。
    3. 返回 ? IsArray(proxyTarget)。
  4. 返回 false。

7.2.3 IsCallable ( arg )

抽象操作 IsCallable,接收参数 arg (ECMAScript 语言值);返回值:Boolean。 它确定 arg 是否是具有 [[Call]] 内部方法的可调用函数。 调用时执行以下步骤:

  1. 如果 arg 不是 Object,则返回 false。
  2. 如果 arg 具有 [[Call]] 内部方法,则返回 true。
  3. 返回 false。

7.2.4 IsConstructor ( arg )

抽象操作 IsConstructor,接收参数 arg (ECMAScript 语言值);返回值:Boolean。 它确定 arg 是否是具有 [[Construct]] 内部方法的函数对象。 调用时执行以下步骤:

  1. 如果 arg 不是 Object,则返回 false。
  2. 如果 arg 具有 [[Construct]] 内部方法,则返回 true。
  3. 返回 false。

7.2.5 IsExtensible ( obj )

抽象操作 IsExtensible,接收参数 obj (Object);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它用于确定是否可以向 obj 添加其他属性。 调用时执行以下步骤:

  1. 返回 ? obj.[[IsExtensible]]()。

7.2.6 IsRegExp ( arg )

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

  1. 如果 arg 不是 Object,则返回 false。
  2. 令 matcher 为 ? Get(arg, %Symbol.match%)。
  3. 如果 matcher 不是 undefined,则返回 ToBoolean(matcher)。
  4. 如果 arg 具有 [[RegExpMatcher]] 内部槽,则返回 true。
  5. 返回 false。

7.2.7 Static Semantics: IsStringWellFormedUnicode ( string )

抽象操作 IsStringWellFormedUnicode,接收参数 string (String);返回值:Boolean。 它按照 6.1.4 中的描述,将 string 解释为 UTF-16 编码的码点序列,并确定它是否是格式良好的 UTF-16 序列。 调用时执行以下步骤:

  1. 令 length 为 string 的长度。
  2. 令 k 为 0。
  3. 当 k < length 时,重复执行
    1. 令 codePoint 为 CodePointAt(string, k)。
    2. 如果 codePoint.[[IsUnpairedSurrogate]] 是 true,则返回 false。
    3. 将 k 设置为 k + codePoint.[[CodeUnitCount]]。
  4. 返回 true。

7.2.8 SameType ( x, y )

抽象操作 SameType,接收参数 x (ECMAScript 语言值) 和 y (ECMAScript 语言值);返回值:Boolean。 它确定两个参数是否具有相同类型。 调用时执行以下步骤:

  1. 如果 x 是 undefined 且 y 是 undefined,则返回 true。
  2. 如果 x 是 null 且 y 是 null,则返回 true。
  3. 如果 x 是 Boolean 且 y 是 Boolean,则返回 true。
  4. 如果 x 是 Number 且 y 是 Number,则返回 true。
  5. 如果 x 是 BigInt 且 y 是 BigInt,则返回 true。
  6. 如果 x 是 Symbol 且 y 是 Symbol,则返回 true。
  7. 如果 x 是 String 且 y 是 String,则返回 true。
  8. 如果 x 是 Object 且 y 是 Object,则返回 true。
  9. 返回 false。

7.2.9 SameValue ( x, y )

抽象操作 SameValue,接收参数 x (ECMAScript 语言值) 和 y (ECMAScript 语言值);返回值:Boolean。 它确定两个参数是否为相同的值。 调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 false,则返回 false。
  2. 如果 x 是 Number,则
    1. 返回 Number::sameValue(x, y)。
  3. 返回 SameValueNonNumber(x, y)。
注

该算法与 IsStrictlyEqual 算法不同之处在于,它将所有 NaN 值视为等价,并区分 +0𝔽 和 -0𝔽。

7.2.10 SameValueZero ( x, y )

抽象操作 SameValueZero,接收参数 x (ECMAScript 语言值) 和 y (ECMAScript 语言值);返回值:Boolean。 它确定两个参数是否为相同的值(忽略 +0𝔽 和 -0𝔽 之间的差异)。 调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 false,则返回 false。
  2. 如果 x 是 Number,则
    1. 返回 Number::sameValueZero(x, y)。
  3. 返回 SameValueNonNumber(x, y)。
注

SameValueZero 与 SameValue 的唯一区别在于,它将 +0𝔽 和 -0𝔽 视为等价。

7.2.11 SameValueNonNumber ( x, y )

抽象操作 SameValueNonNumber,接收参数 x (an ECMAScript language value, but not a Number) 和 y (an ECMAScript language value, but not a Number);返回值:Boolean。 调用时执行以下步骤:

  1. 断言:SameType(x, y) 是 true。
  2. 如果 x 是 undefined 或 null,则返回 true。
  3. 如果 x 是 BigInt,则
    1. 返回 BigInt::equal(x, y)。
  4. 如果 x 是 String,则
    1. 如果 x 和 y 长度相同,并且相同位置具有相同码元,则返回 true。
    2. 返回 false。
  5. 如果 x 是 Boolean,则
    1. 如果 x 是 true 且 y 是 true,则返回 true。
    2. 如果 x 是 false 且 y 是 false,则返回 true。
    3. 返回 false。
  6. 注:所有其他 ECMAScript 语言值都按标识进行比较。
  7. 如果 x 是 y,则返回 true。
  8. 返回 false。
注 1
为了便于说明,即使没有必要,本算法中的某些情况也会单独处理。
注 2
“x 是 y”的具体含义详见 5.2.8。

7.2.12 IsLessThan ( x, y, leftFirst )

抽象操作 IsLessThan,接收参数 x (ECMAScript 语言值)、y (ECMAScript 语言值) 和 leftFirst (Boolean);返回值:(正常完成 (值:(Boolean 或 undefined)) 或 抛出完成)。 它提供比较 x < y 的语义,返回 true、false 或 undefined(后者表示操作数无法被强制转换为相同数值类型的可比较值)。leftFirst 标志用于控制对 x 和 y 执行可能具有可见副作用的操作的顺序。这是必要的,因为 ECMAScript 规定表达式从左到右求值。如果 leftFirst 是 true,则 x 参数对应的表达式位于 y 参数对应表达式的左侧。如果 leftFirst 是 false,情况相反,必须先对 y 执行操作,再对 x 执行。 调用时执行以下步骤:

  1. 如果 leftFirst 是 true,则
    1. 令 px 为 ? ToPrimitive(x, number)。
    2. 令 py 为 ? ToPrimitive(y, number)。
  2. 否则,
    1. 注:需要反转求值顺序,以保持从左到右的求值。
    2. 令 py 为 ? ToPrimitive(y, number)。
    3. 令 px 为 ? ToPrimitive(x, number)。
  3. 如果 px 是 String 且 py 是 String,则
    1. 令 lx 为 px 的长度。
    2. 令 ly 为 py 的长度。
    3. 对满足 0 ≤ i < min(lx, ly) 的每个整数 i,按升序执行
      1. 令 cx 为 px 中索引 i 处码元的数值。
      2. 令 cy 为 py 中索引 i 处码元的数值。
      3. 如果 cx < cy,则返回 true。
      4. 如果 cx > cy,则返回 false。
    4. 如果 lx < ly,则返回 true。
    5. 返回 false。
  4. 如果 px 是 BigInt 且 py 是 String,则
    1. 令 ny 为 StringToBigInt(py)。
    2. 如果 ny 是 undefined,则返回 undefined。
    3. 返回 BigInt::lessThan(px, ny)。
  5. 如果 px 是 String 且 py 是 BigInt,则
    1. 令 nx 为 StringToBigInt(px)。
    2. 如果 nx 是 undefined,则返回 undefined。
    3. 返回 BigInt::lessThan(nx, py)。
  6. 注:由于 px 和 py 是原始值,因此求值顺序不重要。
  7. 令 nx 为 ? ToNumeric(px)。
  8. 令 ny 为 ? ToNumeric(py)。
  9. 如果 SameType(nx, ny) 是 true,则
    1. 如果 nx 是 Number,则返回 Number::lessThan(nx, ny)。
    2. 断言:nx 是 BigInt。
    3. 返回 BigInt::lessThan(nx, ny)。
  10. 断言:nx 是 BigInt 且 ny 是 Number,或者 nx 是 Number 且 ny 是 BigInt。
  11. 如果 nx 是 NaN 或 ny 是 NaN,则返回 undefined。
  12. 如果 nx 是 -∞𝔽 或 ny 是 +∞𝔽,则返回 true。
  13. 如果 nx 是 +∞𝔽 或 ny 是 -∞𝔽,则返回 false。
  14. 如果 ℝ(nx) < ℝ(ny),则返回 true。
  15. 返回 false。
注 1

步骤 3 与处理加法运算符 + 的算法(13.15.3)中的步骤 1.c 不同,因为它使用逻辑与操作,而不是逻辑或操作。

注 2

String 的比较使用 UTF-16 码元值序列上的简单字典序。不会尝试使用 Unicode 规范中定义的、语义上更复杂的字符或字符串相等性以及排序顺序定义。因此,根据 Unicode 标准规范等价、但不处于相同规范化形式的 String 值可能会比较为不相等。还要注意,对于包含代理对的 String,按码元字典排序与按码点排序不同。

7.2.13 IsLooselyEqual ( x, y )

抽象操作 IsLooselyEqual,接收参数 x (ECMAScript 语言值) 和 y (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它提供 == 运算符的语义。 调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 true,那么
    1. 返回 IsStrictlyEqual(x, y)。
  2. 如果 x 是 null 且 y 是 undefined,返回 true。
  3. 如果 x 是 undefined 且 y 是 null,返回 true。
  4. Normative Optional
    如果宿主是 Web 浏览器或以其他方式支持 [[IsHTMLDDA]] 内部槽,那么
    1. 如果 x 是 Object,x 具有 [[IsHTMLDDA]] 内部槽,并且 y 是 undefined 或 null,返回 true。
    2. 如果 x 是 undefined 或 null,y 是 Object,并且 y 具有 [[IsHTMLDDA]] 内部槽,返回 true。
  5. 如果 x 是 Number 且 y 是 String,返回 ! IsLooselyEqual(x, ! ToNumber(y))。
  6. 如果 x 是 String 且 y 是 Number,返回 ! IsLooselyEqual(! ToNumber(x), y)。
  7. 如果 x 是 BigInt 且 y 是 String,那么
    1. 令 n 为 StringToBigInt(y)。
    2. 如果 n 是 undefined,返回 false。
    3. 返回 ! IsLooselyEqual(x, n)。
  8. 如果 x 是 String 且 y 是 BigInt,返回 ! IsLooselyEqual(y, x)。
  9. 如果 x 是 Boolean,返回 ! IsLooselyEqual(! ToNumber(x), y)。
  10. 如果 y 是 Boolean,返回 ! IsLooselyEqual(x, ! ToNumber(y))。
  11. 如果 x 是 String、Number、BigInt 或 Symbol,且 y 是 Object,返回 ! IsLooselyEqual(x, ? ToPrimitive(y))。
  12. 如果 x 是 Object,且 y 是 String、Number、BigInt 或 Symbol,返回 ! IsLooselyEqual(? ToPrimitive(x), y)。
  13. 如果 x 是 BigInt 且 y 是有限 Number,或者 x 是有限 Number 且 y 是 BigInt,那么
    1. 如果 ℝ(x) = ℝ(y),返回 true。
    2. 返回 false。
  14. 返回 false。

7.2.14 IsStrictlyEqual ( x, y )

抽象操作 IsStrictlyEqual,接收参数 x (ECMAScript 语言值) 和 y (ECMAScript 语言值);返回值:Boolean。 它提供 === 运算符的语义。 调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 false,则返回 false。
  2. 如果 x 是 Number,则
    1. 返回 Number::equal(x, y)。
  3. 返回 SameValueNonNumber(x, y)。
注

该算法与 SameValue 算法在处理有符号零和 NaN 时有所不同。

7.3 对象上的操作

7.3.1 MakeBasicObject ( internalSlotsList )

抽象操作 MakeBasicObject,接收参数 internalSlotsList (列表 (元素:内部槽名称));返回值:Object。 它是所有通过算法创建的 ECMAScript 对象(包括普通对象和异质对象)的来源。它提取创建所有对象时使用的公共步骤,并将对象创建集中在一起。 调用时执行以下步骤:

  1. 将 internalSlotsList 设置为 internalSlotsList 与 « [[PrivateElements]] » 的列表连接。
  2. 令 obj 为新创建的对象,该对象为 internalSlotsList 中的每个名称都具有一个内部槽。
  3. 注:如 Object 内部方法和内部槽 所述,除非另有规定,否则每个此类内部槽的初始值都是 undefined。
  4. 将 obj.[[PrivateElements]] 设置为新的空 List。
  5. 将 obj 的基本内部方法设置为 10.1 中规定的默认普通对象定义。
  6. 断言:如果调用方不会同时覆盖 obj 的 [[GetPrototypeOf]] 和 [[SetPrototypeOf]] 基本内部方法,则 internalSlotsList 包含 [[Prototype]]。
  7. 断言:如果调用方不会覆盖 obj 的 [[SetPrototypeOf]]、[[IsExtensible]] 和 [[PreventExtensions]] 全部三个基本内部方法,则 internalSlotsList 包含 [[Extensible]]。
  8. 如果 internalSlotsList 包含 [[Extensible]],则将 obj.[[Extensible]] 设置为 true。
  9. 返回 obj。
注

在本规范中,异质对象通过 ArrayCreate 和 BoundFunctionCreate 等抽象操作创建:首先调用 MakeBasicObject 获取基本的基础对象,然后覆盖该对象的部分或全部内部方法。为了封装异质对象的创建,对象的基本内部方法绝不会在这些操作之外被修改。

7.3.2 Get ( obj, propertyKey )

抽象操作 Get,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它用于检索对象的特定属性值。 调用时执行以下步骤:

  1. 返回 ? obj.[[Get]](propertyKey, obj)。

7.3.3 GetV ( value, propertyKey )

抽象操作 GetV,接收参数 value (ECMAScript 语言值) 和 propertyKey (属性键);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它用于检索 ECMAScript 语言值的特定属性值。如果该值不是对象,则使用适合该值类型的包装对象执行属性查找。 调用时执行以下步骤:

  1. 令 obj 为 ? ToObject(value)。
  2. 返回 ? obj.[[Get]](propertyKey, value)。

7.3.4 Set ( obj, propertyKey, value, throw )

抽象操作 Set,接收参数 obj (Object)、propertyKey (属性键)、value (ECMAScript 语言值) 和 throw (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。 它用于设置对象的特定属性值。value 是该属性的新值。 调用时执行以下步骤:

  1. 令 success 为 ? obj.[[Set]](propertyKey, value, obj)。
  2. 如果 success 是 false 且 throw 是 true,则抛出 TypeError 异常。
  3. 返回 unused。

7.3.5 CreateDataProperty ( obj, propertyKey, value )

抽象操作 CreateDataProperty,接收参数 obj (Object)、propertyKey (属性键) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它用于创建对象的新自有属性。 调用时执行以下步骤:

  1. 令 newDesc 为 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 返回 ? obj.[[DefineOwnProperty]](propertyKey, newDesc)。
注

此抽象操作创建一个属性,其特性设置为与 ECMAScript 语言赋值运算符创建的属性相同的默认值。通常,该属性尚不存在。如果它已经存在且不可配置,或者 obj 不可扩展,则 [[DefineOwnProperty]] 将返回 false。

7.3.6 CreateDataPropertyOrThrow ( obj, propertyKey, value )

抽象操作 CreateDataPropertyOrThrow,接收参数 obj (Object)、propertyKey (属性键) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 它用于创建对象的新自有属性。如果无法执行所请求的属性更新,则抛出 TypeError 异常。 调用时执行以下步骤:

  1. 令 success 为 ? CreateDataProperty(obj, propertyKey, value)。
  2. 如果 success 是 false,则抛出 TypeError 异常。
  3. 返回 unused。
注

此抽象操作创建一个属性,其特性设置为与 ECMAScript 语言赋值运算符创建的属性相同的默认值。通常,该属性尚不存在。如果它已经存在且不可配置,或者 obj 不可扩展,则 [[DefineOwnProperty]] 将返回 false,从而导致此操作抛出 TypeError 异常。

7.3.7 CreateNonEnumerableDataPropertyOrThrow ( obj, propertyKey, value )

抽象操作 CreateNonEnumerableDataPropertyOrThrow,接收参数 obj (Object)、propertyKey (属性键) 和 value (ECMAScript 语言值);返回值:unused。 它用于创建普通对象的新不可枚举自有属性。 调用时执行以下步骤:

  1. 断言:obj 是普通、可扩展且没有不可配置属性的对象。
  2. 令 newDesc 为 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }。
  3. 执行 ! DefinePropertyOrThrow(obj, propertyKey, newDesc)。
  4. 返回 unused。
注

此抽象操作创建一个属性,其特性设置为与 ECMAScript 语言赋值运算符创建的属性相同的默认值,但它不可枚举。通常,该属性尚不存在。如果它已经存在,则保证 DefinePropertyOrThrow 正常完成。

7.3.8 DefinePropertyOrThrow ( obj, propertyKey, propertyDesc )

抽象操作 DefinePropertyOrThrow,接收参数 obj (Object)、propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:unused) 或 抛出完成)。 它用于调用对象的 [[DefineOwnProperty]] 内部方法,并在无法执行所请求的属性更新时抛出 TypeError 异常。 调用时执行以下步骤:

  1. 令 success 为 ? obj.[[DefineOwnProperty]](propertyKey, propertyDesc)。
  2. 如果 success 是 false,则抛出 TypeError 异常。
  3. 返回 unused。

7.3.9 DeletePropertyOrThrow ( obj, propertyKey )

抽象操作 DeletePropertyOrThrow,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(正常完成 (值:unused) 或 抛出完成)。 它用于移除对象的特定自有属性。如果该属性不可配置,则抛出异常。 调用时执行以下步骤:

  1. 令 success 为 ? obj.[[Delete]](propertyKey)。
  2. 如果 success 是 false,则抛出 TypeError 异常。
  3. 返回 unused。

7.3.10 GetMethod ( value, propertyKey )

抽象操作 GetMethod,接收参数 value (ECMAScript 语言值) 和 propertyKey (属性键);返回值:(正常完成 (值:(函数对象 或 undefined)) 或 抛出完成)。 当预期 ECMAScript 语言值的某个特定属性值为函数时,它用于获取该属性的值。 调用时执行以下步骤:

  1. 令 func 为 ? GetV(value, propertyKey)。
  2. 如果 func 是 undefined 或 null,则返回 undefined。
  3. 如果 IsCallable(func) 是 false,则抛出 TypeError 异常。
  4. 返回 func。

7.3.11 HasProperty ( obj, propertyKey )

抽象操作 HasProperty,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它用于确定对象是否具有指定属性键的属性。该属性可以是自有属性,也可以是继承属性。 调用时执行以下步骤:

  1. 返回 ? obj.[[HasProperty]](propertyKey)。

7.3.12 HasOwnProperty ( obj, propertyKey )

抽象操作 HasOwnProperty,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它用于确定对象是否具有指定属性键的自有属性。 调用时执行以下步骤:

  1. 令 propertyDesc 为 ? obj.[[GetOwnProperty]](propertyKey)。
  2. 如果 propertyDesc 是 undefined,则返回 false。
  3. 返回 true。

7.3.13 Call ( func, thisValue [ , argList ] )

抽象操作 Call,接收参数 func (ECMAScript 语言值) 和 thisValue (ECMAScript 语言值)和可选参数 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它用于调用函数对象的 [[Call]] 内部方法。func 是函数对象,thisValue 是作为 [[Call]] 的 this 值的 ECMAScript 语言值,argList 是传递给内部方法相应参数的值。如果不存在 argList,则使用新的空 List 作为其值。 调用时执行以下步骤:

  1. 如果不存在 argList,则将 argList 设置为新的空 List。
  2. 如果 IsCallable(func) 是 false,则抛出 TypeError 异常。
  3. 返回 ? func.[[Call]](thisValue, argList)。

7.3.14 Construct ( ctor [ , argList [ , newTarget ] ] )

抽象操作 Construct,接收参数 ctor (构造函数)和可选参数 argList (列表 (元素:ECMAScript 语言值)) 和 newTarget (构造函数);返回值:(正常完成 (值:Object) 或 抛出完成)。 它用于调用函数对象的 [[Construct]] 内部方法。argList 和 newTarget 是要作为内部方法相应参数传递的值。如果不存在 argList,则使用新的空 List 作为其值。如果不存在 newTarget,则使用 ctor 作为其值。 调用时执行以下步骤:

  1. 如果不存在 newTarget,则将 newTarget 设置为 ctor。
  2. 如果不存在 argList,则将 argList 设置为新的空 List。
  3. 返回 ? ctor.[[Construct]](argList, newTarget)。
注

如果不存在 newTarget,此操作等价于:new F(...argumentsList)

7.3.15 SetIntegrityLevel ( obj, level )

抽象操作 SetIntegrityLevel,接收参数 obj (Object) 和 level ((sealed 或 frozen));返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它用于固定对象的自有属性集合。 调用时执行以下步骤:

  1. 令 status 为 ? obj.[[PreventExtensions]]()。
  2. 如果 status 是 false,则返回 false。
  3. 令 keys 为 ? obj.[[OwnPropertyKeys]]()。
  4. 如果 level 是 sealed,则
    1. 对 keys 的每个元素 key,执行
      1. 执行 ? DefinePropertyOrThrow(obj, key, PropertyDescriptor { [[Configurable]]: false })。
  5. 否则,
    1. 断言:level 是 frozen。
    2. 对 keys 的每个元素 key,执行
      1. 令 currentDesc 为 ? obj.[[GetOwnProperty]](key)。
      2. 如果 currentDesc 不是 undefined,则
        1. 如果 IsAccessorDescriptor(currentDesc) 是 true,则
          1. 令 propertyDesc 为 PropertyDescriptor { [[Configurable]]: false }。
        2. 否则,
          1. 令 propertyDesc 为 PropertyDescriptor { [[Configurable]]: false, [[Writable]]: false }。
        3. 执行 ? DefinePropertyOrThrow(obj, key, propertyDesc)。
  6. 返回 true。

7.3.16 TestIntegrityLevel ( obj, level )

抽象操作 TestIntegrityLevel,接收参数 obj (Object) 和 level ((sealed 或 frozen));返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它用于确定对象的自有属性集合是否已固定。 调用时执行以下步骤:

  1. 令 extensible 为 ? IsExtensible(obj)。
  2. 如果 extensible 是 true,则返回 false。
  3. 注:如果对象可扩展,则不会检查其任何属性。
  4. 令 keys 为 ? obj.[[OwnPropertyKeys]]()。
  5. 对 keys 的每个元素 key,执行
    1. 令 currentDesc 为 ? obj.[[GetOwnProperty]](key)。
    2. 如果 currentDesc 不是 undefined,则
      1. 如果 currentDesc.[[Configurable]] 是 true,则返回 false。
      2. 如果 level 是 frozen 且 IsDataDescriptor(currentDesc) 是 true,则
        1. 如果 currentDesc.[[Writable]] 是 true,则返回 false。
  6. 返回 true。

7.3.17 CreateArrayFromList ( elements )

抽象操作 CreateArrayFromList,接收参数 elements (列表 (元素:ECMAScript 语言值));返回值:Array。 它用于创建一个 Array,其元素由 elements 提供。 调用时执行以下步骤:

  1. 令 array 为 ! ArrayCreate(0)。
  2. 令 n 为 0。
  3. 对 elements 的每个元素 element,执行
    1. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), element)。
    2. 将 n 设置为 n + 1。
  4. 返回 array。

7.3.18 LengthOfArrayLike ( obj )

抽象操作 LengthOfArrayLike,接收参数 obj (Object);返回值:(正常完成 (值:非负整数) 或 抛出完成)。 它返回类数组对象的 "length" 属性值。 调用时执行以下步骤:

  1. 返回 ℝ(? ToLength(? Get(obj, "length")))。

类数组对象是此操作对其返回正常完成的任何对象。

注 1
通常,类数组对象还会具有一些名称为整数索引的属性。但是,这并不是此定义的要求。
注 2
Array 和 String 对象都是类数组对象的示例。

7.3.19 CreateListFromArrayLike ( obj [ , validElementTypes ] )

抽象操作 CreateListFromArrayLike,接收参数 obj (ECMAScript 语言值)和可选参数 validElementTypes ((all 或 property-key));返回值:(正常完成 (值:列表 (元素:ECMAScript 语言值)) 或 抛出完成)。 它用于创建一个 List 值,其元素由 obj 的索引属性提供。validElementTypes 指示允许作为元素的值类型。 调用时执行以下步骤:

  1. 如果不存在 validElementTypes,则将 validElementTypes 设置为 all。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 length 为 ? LengthOfArrayLike(obj)。
  4. 令 list 为新的空 List。
  5. 令 index 为 0。
  6. 当 index < length 时,重复执行
    1. 令 indexName 为 ! ToString(𝔽(index))。
    2. 令 next 为 ? Get(obj, indexName)。
    3. 如果 validElementTypes 是 property-key 且 next 不是属性键,则抛出 TypeError 异常。
    4. 将 next 追加到 list。
    5. 将 index 设置为 index + 1。
  7. 返回 list。

7.3.20 Invoke ( value, propertyKey [ , argList ] )

抽象操作 Invoke,接收参数 value (ECMAScript 语言值) 和 propertyKey (属性键)和可选参数 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它用于调用 ECMAScript 语言值的方法属性。value 既作为属性查找位置,也作为调用的 this 值。argList 是传递给该方法的参数值列表。如果不存在 argList,则使用新的空 List 作为其值。 调用时执行以下步骤:

  1. 如果不存在 argList,则将 argList 设置为新的空 List。
  2. 令 func 为 ? GetV(value, propertyKey)。
  3. 返回 ? Call(func, value, argList)。

7.3.21 OrdinaryHasInstance ( ctor, instance )

抽象操作 OrdinaryHasInstance,接收参数 ctor (ECMAScript 语言值) 和 instance (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它实现默认算法,用于确定 instance 是否继承自 ctor 提供的实例对象继承路径。 调用时执行以下步骤:

  1. 如果 IsCallable(ctor) 是 false,则返回 false。
  2. 如果 ctor 具有 [[BoundTargetFunction]] 内部槽,则
    1. 令 boundCtor 为 ctor.[[BoundTargetFunction]]。
    2. 返回 ? InstanceofOperator(instance, boundCtor)。
  3. 如果 instance 不是 Object,则返回 false。
  4. 令 proto 为 ? Get(ctor, "prototype")。
  5. 如果 proto 不是 Object,则抛出 TypeError 异常。
  6. 重复执行,
    1. 将 instance 设置为 ? instance.[[GetPrototypeOf]]()。
    2. 如果 instance 是 null,则返回 false。
    3. 如果 SameValue(proto, instance) 是 true,则返回 true。

7.3.22 SpeciesConstructor ( obj, defaultCtor )

抽象操作 SpeciesConstructor,接收参数 obj (Object) 和 defaultCtor (构造函数);返回值:(正常完成 (值:构造函数) 或 抛出完成)。 它用于检索应当用来创建从 obj 派生的新对象的构造函数。如果从 obj 开始无法找到构造函数的 %Symbol.species% 属性,则使用 defaultCtor。 调用时执行以下步骤:

  1. 令 ctor 为 ? Get(obj, "constructor")。
  2. 如果 ctor 是 undefined,则返回 defaultCtor。
  3. 如果 ctor 不是 Object,则抛出 TypeError 异常。
  4. 令 species 为 ? Get(ctor, %Symbol.species%)。
  5. 如果 species 是 undefined 或 null,则返回 defaultCtor。
  6. 如果 IsConstructor(species) 是 true,则返回 species。
  7. 抛出 TypeError 异常。

7.3.23 EnumerableOwnProperties ( obj, kind )

抽象操作 EnumerableOwnProperties,接收参数 obj (Object) 和 kind ((key、value 或 key+value));返回值:(正常完成 (值:列表 (元素:ECMAScript 语言值)) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 ownKeys 为 ? obj.[[OwnPropertyKeys]]()。
  2. 令 results 为新的空 List。
  3. 对 ownKeys 的每个元素 key,执行
    1. 如果 key 是 String,则
      1. 令 propertyDesc 为 ? obj.[[GetOwnProperty]](key)。
      2. 如果 propertyDesc 不是 undefined 且 propertyDesc.[[Enumerable]] 是 true,则
        1. 如果 kind 是 key,则
          1. 将 key 追加到 results。
        2. 否则,
          1. 令 value 为 ? Get(obj, key)。
          2. 如果 kind 是 value,则
            1. 将 value 追加到 results。
          3. 否则,
            1. 断言:kind 是 key+value。
            2. 令 entry 为 CreateArrayFromList(« key, value »)。
            3. 将 entry 追加到 results。
  4. 返回 results。

7.3.24 GetFunctionRealm ( func )

抽象操作 GetFunctionRealm,接收参数 func (函数对象);返回值:(正常完成 (值:Realm 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 func 具有 [[Realm]] 内部槽,则
    1. 返回 func.[[Realm]]。
  2. 如果 func 是绑定函数异质对象,则
    1. 令 boundTargetFunc 为 func.[[BoundTargetFunction]]。
    2. 返回 ? GetFunctionRealm(boundTargetFunc)。
  3. 如果 func 是 Proxy 异质对象,则
    1. 执行 ? ValidateNonRevokedProxy(func)。
    2. 令 proxyTarget 为 func.[[ProxyTarget]]。
    3. 断言:proxyTarget 是函数对象。
    4. 返回 ? GetFunctionRealm(proxyTarget)。
  4. 返回当前 Realm Record。
注

只有当 func 是不具有 [[Realm]] 内部槽的非标准函数异质对象时,才会到达步骤 4。

7.3.25 CopyDataProperties ( target, source, excludedItems )

抽象操作 CopyDataProperties,接收参数 target (Object)、source (ECMAScript 语言值) 和 excludedItems (列表 (元素:属性键));返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 source 是 undefined 或 null,则返回 unused。
  2. 令 from 为 ! ToObject(source)。
  3. 令 keys 为 ? from.[[OwnPropertyKeys]]()。
  4. 对 keys 的每个元素 nextKey,执行
    1. 令 excluded 为 false。
    2. 对 excludedItems 的每个元素 element,执行
      1. 如果 SameValue(element, nextKey) 是 true,则
        1. 将 excluded 设置为 true。
    3. 如果 excluded 是 false,则
      1. 令 propertyDesc 为 ? from.[[GetOwnProperty]](nextKey)。
      2. 如果 propertyDesc 不是 undefined 且 propertyDesc.[[Enumerable]] 是 true,则
        1. 令 propertyValue 为 ? Get(from, nextKey)。
        2. 执行 ! CreateDataPropertyOrThrow(target, nextKey, propertyValue)。
  5. 返回 unused。
注

此处传入的目标始终是新创建的对象,在抛出错误的情况下无法直接访问它。

7.3.26 PrivateElementFind ( obj, privateName )

抽象操作 PrivateElementFind,接收参数 obj (Object) 和 privateName (私有名称);返回值:(PrivateElement 或 empty)。 调用时执行以下步骤:

  1. 如果 obj.[[PrivateElements]] 包含一个 PrivateElement entry,使得 entry.[[Key]] 是 privateName,则
    1. 返回 entry。
  2. 返回 empty。

7.3.27 PrivateFieldAdd ( obj, privateName, value )

抽象操作 PrivateFieldAdd,接收参数 obj (Object)、privateName (私有名称) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果宿主是 Web 浏览器,则
    1. 执行 ? HostEnsureCanAddPrivateElement(obj)。
  2. 令 entry 为 PrivateElementFind(obj, privateName)。
  3. 如果 entry 不是 empty,则抛出 TypeError 异常。
  4. 将 PrivateElement { [[Key]]: privateName, [[Kind]]: field, [[Value]]: value } 追加到 obj.[[PrivateElements]]。
  5. 返回 unused。

7.3.28 PrivateMethodOrAccessorAdd ( obj, method )

抽象操作 PrivateMethodOrAccessorAdd,接收参数 obj (Object) 和 method (PrivateElement);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 断言:method.[[Kind]] 是 method 或 accessor。
  2. 如果宿主是 Web 浏览器,则
    1. 执行 ? HostEnsureCanAddPrivateElement(obj)。
  3. 令 entry 为 PrivateElementFind(obj, method.[[Key]])。
  4. 如果 entry 不是 empty,则抛出 TypeError 异常。
  5. 将 method 追加到 obj.[[PrivateElements]]。
  6. 返回 unused。
注

私有方法和访问器的值在各实例之间共享。此操作不会创建方法或访问器的新副本。

7.3.29 HostEnsureCanAddPrivateElement ( obj )

宿主定义的抽象操作 HostEnsureCanAddPrivateElement,接收参数 obj (Object);返回值:(正常完成 (值:unused) 或 抛出完成)。 它允许宿主环境阻止向特定宿主定义的异质对象添加私有元素。

HostEnsureCanAddPrivateElement 的实现必须符合以下要求:

HostEnsureCanAddPrivateElement 的默认实现是返回 NormalCompletion(unused)。

只有作为 Web 浏览器的 ECMAScript 宿主才会调用此抽象操作。

7.3.30 PrivateGet ( obj, privateName )

抽象操作 PrivateGet,接收参数 obj (Object) 和 privateName (私有名称);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 entry 为 PrivateElementFind(obj, privateName)。
  2. 如果 entry 是 empty,则抛出 TypeError 异常。
  3. 如果 entry.[[Kind]] 是 field 或 method,则
    1. 返回 entry.[[Value]]。
  4. 断言:entry.[[Kind]] 是 accessor。
  5. 如果 entry.[[Getter]] 是 undefined,则抛出 TypeError 异常。
  6. 令 getter 为 entry.[[Getter]]。
  7. 返回 ? Call(getter, obj)。

7.3.31 PrivateSet ( obj, privateName, value )

抽象操作 PrivateSet,接收参数 obj (Object)、privateName (私有名称) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 entry 为 PrivateElementFind(obj, privateName)。
  2. 如果 entry 是 empty,则抛出 TypeError 异常。
  3. 如果 entry.[[Kind]] 是 method,则抛出 TypeError 异常。
  4. 如果 entry.[[Kind]] 是 field,则
    1. 将 entry.[[Value]] 设置为 value。
  5. 否则,
    1. 断言:entry.[[Kind]] 是 accessor。
    2. 如果 entry.[[Setter]] 是 undefined,则抛出 TypeError 异常。
    3. 令 setter 为 entry.[[Setter]]。
    4. 执行 ? Call(setter, obj, « value »)。
  6. 返回 unused。

7.3.32 DefineField ( receiver, fieldRecord )

抽象操作 DefineField,接收参数 receiver (Object) 和 fieldRecord (ClassFieldDefinition 记录);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 fieldName 为 fieldRecord.[[Name]]。
  2. 令 initializer 为 fieldRecord.[[Initializer]]。
  3. 如果 initializer 不是 empty,则
    1. 令 initValue 为 ? Call(initializer, receiver)。
  4. 否则,
    1. 令 initValue 为 undefined。
  5. 如果 fieldName 是 Private Name,则
    1. 执行 ? PrivateFieldAdd(receiver, fieldName, initValue)。
  6. 否则,
    1. 断言:fieldName 是属性键。
    2. 执行 ? CreateDataPropertyOrThrow(receiver, fieldName, initValue)。
  7. 返回 unused。

7.3.33 InitializeInstanceElements ( obj, ctor )

抽象操作 InitializeInstanceElements,接收参数 obj (Object) 和 ctor ((ECMAScript 函数对象 或 内置函数对象));返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 methods 为 ctor.[[PrivateMethods]]。
  2. 对 methods 的每个 PrivateElement method,执行
    1. 执行 ? PrivateMethodOrAccessorAdd(obj, method)。
  3. 令 fields 为 ctor.[[Fields]]。
  4. 对 fields 的每个元素 fieldRecord,执行
    1. 执行 ? DefineField(obj, fieldRecord)。
  5. 返回 unused。

7.3.34 AddValueToKeyedGroup ( groups, key, value )

抽象操作 AddValueToKeyedGroup,接收参数 groups (列表 (元素:记录 (字段:[[Key]] (ECMAScript 语言值), [[Elements]] (列表 (元素:ECMAScript 语言值)))))、key (ECMAScript 语言值) 和 value (ECMAScript 语言值);返回值:unused。 调用时执行以下步骤:

  1. 对 groups 的每个 Record { [[Key]], [[Elements]] } group,执行
    1. 如果 SameValue(group.[[Key]], key) 是 true,则
      1. 断言:groups 中恰好有一个元素满足此条件。
      2. 将 value 追加到 group.[[Elements]]。
      3. 返回 unused。
  2. 令 group 为 Record { [[Key]]: key, [[Elements]]: « value » }。
  3. 将 group 追加到 groups。
  4. 返回 unused。

7.3.35 GroupBy ( items, callback, keyCoercion )

抽象操作 GroupBy,接收参数 items (ECMAScript 语言值)、callback (ECMAScript 语言值) 和 keyCoercion ((property 或 collection));返回值:(正常完成 (值:列表 (元素:记录 (字段:[[Key]] (ECMAScript 语言值), [[Elements]] (列表 (元素:ECMAScript 语言值))))) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? RequireObjectCoercible(items)。
  2. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  3. 令 groups 为新的空 List。
  4. 令 iteratorRecord 为 ? GetIterator(items, sync)。
  5. 令 k 为 0。
  6. 重复执行,
    1. 如果 k ≥ 253 - 1,则
      1. 令 error 为 ThrowCompletion(新创建的 TypeError 对象)。
      2. 返回 ? IteratorClose(iteratorRecord, error)。
    2. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 next 是 done,则
      1. 返回 groups。
    4. 令 value 为 next。
    5. 令 key 为 Completion(Call(callback, undefined, « value, 𝔽(k) »))。
    6. IfAbruptCloseIterator(key, iteratorRecord)。
    7. 如果 keyCoercion 是 property,则
      1. 将 key 设置为 Completion(ToPropertyKey(key))。
      2. IfAbruptCloseIterator(key, iteratorRecord)。
    8. 否则,
      1. 断言:keyCoercion 是 collection。
      2. 将 key 设置为 CanonicalizeKeyedCollectionKey(key)。
    9. 执行 AddValueToKeyedGroup(groups, key, value)。
    10. 将 k 设置为 k + 1。

7.3.36 GetOptionsObject ( options )

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

  1. 如果 options 是 undefined,则
    1. 返回 OrdinaryObjectCreate(null)。
  2. 如果 options 是 Object,则
    1. 返回 options。
  3. 抛出 TypeError 异常。

7.3.37 SetterThatIgnoresPrototypeProperties ( thisValue, home, propertyKey, value )

抽象操作 SetterThatIgnoresPrototypeProperties,接收参数 thisValue (ECMAScript 语言值)、home (Object)、propertyKey (属性键) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 thisValue 不是 Object,则
    1. 抛出 TypeError 异常。
  2. 如果 SameValue(thisValue, home) 是 true,则
    1. 注:在此处抛出异常模拟了严格模式代码中向 home 对象上的不可写数据属性进行赋值。
    2. 抛出 TypeError 异常。
  3. 令 propertyDesc 为 ? thisValue.[[GetOwnProperty]](propertyKey)。
  4. 如果 propertyDesc 是 undefined,则
    1. 执行 ? CreateDataPropertyOrThrow(thisValue, propertyKey, value)。
  5. 否则,
    1. 执行 ? Set(thisValue, propertyKey, value, true)。
  6. 返回 unused。

7.4 迭代器对象上的操作

参见通用迭代接口(27.1)。

7.4.1 Iterator Record

Iterator Record 是用于封装迭代器或异步迭代器及其 next 方法的 Record。

Iterator Record 具有 表 13 中列出的字段。

表 13: Iterator Record 字段
字段名称 值 含义
[[Iterator]] Object 符合迭代器接口或异步迭代器接口的对象。
[[NextMethod]] ECMAScript 语言值 [[Iterator]] 对象的 next 方法。
[[Done]] Boolean 迭代器是否已经完成或关闭。

7.4.2 GetIteratorDirect ( obj )

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

  1. 令 nextMethod 为 ? Get(obj, "next")。
  2. 令 iteratorRecord 为 Iterator Record { [[Iterator]]: obj, [[NextMethod]]: nextMethod, [[Done]]: false }。
  3. 返回 iteratorRecord。

7.4.3 GetIteratorFromMethod ( obj, method )

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

  1. 令 iterator 为 ? Call(method, obj)。
  2. 如果 iterator 不是 Object,则抛出 TypeError 异常。
  3. 返回 ? GetIteratorDirect(iterator)。

7.4.4 GetIterator ( obj, kind )

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

  1. 如果 kind 是 async,则
    1. 令 method 为 ? GetMethod(obj, %Symbol.asyncIterator%)。
    2. 如果 method 是 undefined,则
      1. 令 syncMethod 为 ? GetMethod(obj, %Symbol.iterator%)。
      2. 如果 syncMethod 是 undefined,则抛出 TypeError 异常。
      3. 令 syncIteratorRecord 为 ? GetIteratorFromMethod(obj, syncMethod)。
      4. 返回 CreateAsyncFromSyncIterator(syncIteratorRecord)。
  2. 否则,
    1. 令 method 为 ? GetMethod(obj, %Symbol.iterator%)。
  3. 如果 method 是 undefined,则抛出 TypeError 异常。
  4. 返回 ? GetIteratorFromMethod(obj, method)。

7.4.5 GetIteratorFlattenable ( obj, primitiveHandling )

抽象操作 GetIteratorFlattenable,接收参数 obj (ECMAScript 语言值) 和 primitiveHandling ((iterate-string-primitives 或 reject-primitives));返回值:(正常完成 (值:Iterator 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 obj 不是 Object,则
    1. 如果 primitiveHandling 是 reject-primitives,则抛出 TypeError 异常。
    2. 断言:primitiveHandling 是 iterate-string-primitives。
    3. 如果 obj 不是 String,则抛出 TypeError 异常。
  2. 令 method 为 ? GetMethod(obj, %Symbol.iterator%)。
  3. 如果 method 是 undefined,则
    1. 令 iterator 为 obj。
  4. 否则,
    1. 令 iterator 为 ? Call(method, obj)。
  5. 如果 iterator 不是 Object,则抛出 TypeError 异常。
  6. 返回 ? GetIteratorDirect(iterator)。

7.4.6 IteratorNext ( iteratorRecord [ , value ] )

抽象操作 IteratorNext,接收参数 iteratorRecord (Iterator 记录)和可选参数 value (ECMAScript 语言值);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果不存在 value,则
    1. 令 result 为 Completion(Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]))。
  2. 否则,
    1. 令 result 为 Completion(Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « value »))。
  3. 如果 result 是抛出完成,则
    1. 将 iteratorRecord.[[Done]] 设置为 true。
    2. 返回 ? result。
  4. 将 result 设置为 ! result。
  5. 如果 result 不是 Object,则
    1. 将 iteratorRecord.[[Done]] 设置为 true。
    2. 抛出 TypeError 异常。
  6. 返回 result。

7.4.7 IteratorComplete ( iteratorResult )

抽象操作 IteratorComplete,接收参数 iteratorResult (Object);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ToBoolean(? Get(iteratorResult, "done")).

7.4.8 IteratorValue ( iteratorResult )

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

  1. 返回 ? Get(iteratorResult, "value")。

7.4.9 IteratorStep ( iteratorRecord )

抽象操作 IteratorStep,接收参数 iteratorRecord (Iterator 记录);返回值:(正常完成 (值:(Object 或 done)) 或 抛出完成)。 它通过调用 iteratorRecord.[[NextMethod]] 从 iteratorRecord.[[Iterator]] 请求下一个值,并返回 done(表示迭代器已到达末尾)或在存在下一个值时返回 IteratorResult 对象。 调用时执行以下步骤:

  1. 令 result 为 ? IteratorNext(iteratorRecord)。
  2. 令 done 为 Completion(IteratorComplete(result))。
  3. 如果 done 是抛出完成,则
    1. 将 iteratorRecord.[[Done]] 设置为 true。
    2. 返回 ? done。
  4. 将 done 设置为 ! done。
  5. 如果 done 是 true,则
    1. 将 iteratorRecord.[[Done]] 设置为 true。
    2. 返回 done。
  6. 返回 result。

7.4.10 IteratorStepValue ( iteratorRecord )

抽象操作 IteratorStepValue,接收参数 iteratorRecord (Iterator 记录);返回值:(正常完成 (值:(ECMAScript 语言值 或 done)) 或 抛出完成)。 它通过调用 iteratorRecord.[[NextMethod]] 从 iteratorRecord.[[Iterator]] 请求下一个值,并返回 done(表示迭代器已到达末尾)或在存在下一个值时返回 IteratorResult 对象中的值。 调用时执行以下步骤:

  1. 令 result 为 ? IteratorStep(iteratorRecord)。
  2. 如果 result 是 done,则
    1. 返回 done。
  3. 令 value 为 Completion(IteratorValue(result))。
  4. 如果 value 是抛出完成,则
    1. 将 iteratorRecord.[[Done]] 设置为 true。
  5. 返回 ? value。

7.4.11 IteratorClose ( iteratorRecord, completion )

抽象操作 IteratorClose,接收参数 iteratorRecord (Iterator 记录) 和 completion (完成记录);返回值:完成记录。 它用于通知迭代器:应执行其在达到完成状态时通常会执行的任何操作。 调用时执行以下步骤:

  1. 断言:iteratorRecord.[[Iterator]] 是 Object。
  2. 令 iterator 为 iteratorRecord.[[Iterator]]。
  3. 令 innerResult 为 Completion(GetMethod(iterator, "return"))。
  4. 如果 innerResult 是正常完成,则
    1. 令 return 为 innerResult.[[Value]]。
    2. 如果 return 是 undefined,则返回 ? completion。
    3. 将 innerResult 设置为 Completion(Call(return, iterator))。
  5. 如果 completion 是抛出完成,则返回 ? completion。
  6. 如果 innerResult 是抛出完成,则返回 ? innerResult。
  7. 如果 innerResult.[[Value]] 不是 Object,则抛出 TypeError 异常。
  8. 返回 ? completion。

7.4.12 IteratorCloseAll ( iterators, completion )

抽象操作 IteratorCloseAll,接收参数 iterators (列表 (元素:Iterator 记录)) 和 completion (完成记录);返回值:完成记录。 调用时执行以下步骤:

  1. 对 iterators 的每个元素 iterator,按 List 的逆序执行
    1. 将 completion 设置为 Completion(IteratorClose(iterator, completion))。
  2. 返回 ? completion。

7.4.13 IfAbruptCloseIterator ( value, iteratorRecord )

IfAbruptCloseIterator 是使用 Iterator Record 的一系列算法步骤的简写。以下形式的算法步骤:

  1. IfAbruptCloseIterator(value, iteratorRecord)。

与以下内容含义相同:

  1. 断言:value 是 Completion Record。
  2. 如果 value 是突然完成,则返回 ? IteratorClose(iteratorRecord, value)。
  3. 将 value 设置为 ! value。

7.4.14 IfAbruptCloseIterators ( value, iteratorRecords )

IfAbruptCloseIterators 是使用 Iterator Record 列表的一系列算法步骤的简写。以下形式的算法步骤:

  1. IfAbruptCloseIterators(value, iteratorRecords)。

与以下内容含义相同:

  1. 断言:value 是 Completion Record。
  2. 如果 value 是突然完成,则返回 ? IteratorCloseAll(iteratorRecords, value)。
  3. 将 value 设置为 ! value。

7.4.15 AsyncIteratorClose ( iteratorRecord, completion )

抽象操作 AsyncIteratorClose,接收参数 iteratorRecord (Iterator 记录) 和 completion (完成记录);返回值:完成记录。 它用于通知异步迭代器:应执行其在达到完成状态时通常会执行的任何操作。 调用时执行以下步骤:

  1. 断言:iteratorRecord.[[Iterator]] 是 Object。
  2. 令 iterator 为 iteratorRecord.[[Iterator]]。
  3. 令 innerResult 为 Completion(GetMethod(iterator, "return"))。
  4. 如果 innerResult 是正常完成,则
    1. 令 return 为 innerResult.[[Value]]。
    2. 如果 return 是 undefined,则返回 ? completion。
    3. 将 innerResult 设置为 Completion(Call(return, iterator))。
    4. 如果 innerResult 是正常完成,则将 innerResult 设置为 Completion(Await(innerResult.[[Value]]))。
  5. 如果 completion 是抛出完成,则返回 ? completion。
  6. 如果 innerResult 是抛出完成,则返回 ? innerResult。
  7. 如果 innerResult.[[Value]] 不是 Object,则抛出 TypeError 异常。
  8. 返回 ? completion。

7.4.16 IfAbruptCloseAsyncIterator ( value, iteratorRecord )

IfAbruptCloseAsyncIterator 是使用 Iterator Record 的一系列算法步骤的简写。以下形式的算法步骤:

  1. IfAbruptCloseAsyncIterator(value, iteratorRecord)。

与以下内容含义相同:

  1. 断言:value 是 Completion Record。
  2. 如果 value 是突然完成,则返回 ? AsyncIteratorClose(iteratorRecord, value)。
  3. 将 value 设置为 ! value。

7.4.17 CreateIteratorResultObject ( value, done )

抽象操作 CreateIteratorResultObject,接收参数 value (ECMAScript 语言值) 和 done (Boolean);返回值:an Object that conforms to the IteratorResult interface。 它创建一个符合 IteratorResult 接口的对象。 调用时执行以下步骤:

  1. 令 obj 为 OrdinaryObjectCreate(%Object.prototype%)。
  2. 执行 ! CreateDataPropertyOrThrow(obj, "value", value)。
  3. 执行 ! CreateDataPropertyOrThrow(obj, "done", done)。
  4. 返回 obj。

7.4.18 CreateListIteratorRecord ( list )

抽象操作 CreateListIteratorRecord,接收参数 list (列表 (元素:ECMAScript 语言值));返回值:Iterator 记录。 它创建一个 Iterator Record,其 [[NextMethod]] 返回 list 中连续的元素。 调用时执行以下步骤:

  1. 令 closure 为一个没有参数的新 Abstract Closure,它捕获 list,并在被调用时执行以下步骤:
    1. 对 list 的每个元素 value,执行
      1. 执行 ? GeneratorYield(CreateIteratorResultObject(value, false))。
    2. 返回 NormalCompletion(undefined)。
  2. 令 iterator 为 CreateIteratorFromClosure(closure, empty, %Iterator.prototype%)。
  3. 返回 Iterator Record { [[Iterator]]: iterator, [[NextMethod]]: %GeneratorPrototype.next%, [[Done]]: false }。
注

列表迭代器对象永远无法被 ECMAScript 代码直接访问。

7.4.19 IteratorToList ( iteratorRecord )

抽象操作 IteratorToList,接收参数 iteratorRecord (Iterator 记录);返回值:(正常完成 (值:列表 (元素:ECMAScript 语言值)) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 values 为新的空 List。
  2. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则
      1. 返回 values。
    3. 将 next 追加到 values。

7.5 可释放对象上的操作

参见通用资源管理接口(27.2.1)。

7.5.1 DisposableResource Record

DisposableResource Record 是用于封装可释放对象以及用于释放该对象的方法的 Record 值。DisposableResource Record 由 CreateDisposableResource 抽象操作产生。

DisposableResource Record 具有 表 14 中列出的字段:

表 14: DisposableResource Record 字段
字段名称 值 含义
[[ResourceValue]] Object 或 undefined 要释放的值。
[[Kind]] sync-dispose 或 async-dispose 表示资源是通过 using 声明或 DisposableStack 对象(sync-dispose)添加,还是通过 await using 声明或 AsyncDisposableStack 对象(async-dispose)添加。
[[DisposeMethod]] 函数对象或 undefined 在释放资源时,将以 [[ResourceValue]] 作为其 this 值调用的函数对象。

7.5.2 AddDisposableResource ( disposableResourceStack, value, kind [ , method ] )

抽象操作 AddDisposableResource,接收参数 disposableResourceStack (列表 (元素:DisposableResource 记录))、value (ECMAScript 语言值) 和 kind ((sync-dispose 或 async-dispose))和可选参数 method (函数对象);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果存在 method,则
    1. 断言:value 是 undefined。
    2. 令 resource 为 ? CreateDisposableResource(undefined, kind, method)。
  2. 否则,
    1. 如果 value 是 null 或 undefined,并且 kind 是 sync-dispose,则返回 unused。
    2. 注:当 value 是 null 或 undefined 且 kind 是 async-dispose 时,我们会记录该资源已被求值,以确保稍后释放资源时仍会执行一次 Await。
    3. 令 resource 为 ? CreateDisposableResource(value, kind)。
  3. 将 resource 追加到 disposableResourceStack。
  4. 返回 unused。

7.5.3 CreateDisposableResource ( value, kind [ , method ] )

抽象操作 CreateDisposableResource,接收参数 value (ECMAScript 语言值) 和 kind ((sync-dispose 或 async-dispose))和可选参数 method (函数对象);返回值:(正常完成 (值:DisposableResource 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果不存在 method,则
    1. 如果 value 是 null 或 undefined,则
      1. 将 value 设置为 undefined。
      2. 将 method 设置为 undefined。
    2. 否则,
      1. 将 method 设置为 ? GetDisposeMethod(value, kind)。
      2. 如果 method 是 undefined,则抛出 TypeError 异常。
  2. 返回 DisposableResource Record { [[ResourceValue]]: value, [[Kind]]: kind, [[DisposeMethod]]: method }。

7.5.4 GetDisposeMethod ( value, kind )

抽象操作 GetDisposeMethod,接收参数 value (ECMAScript 语言值) 和 kind ((sync-dispose 或 async-dispose));返回值:(正常完成 (值:(函数对象 或 undefined)) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 value 不是 Object,则抛出 TypeError 异常。
  2. 如果 kind 是 sync-dispose,则返回 ? GetMethod(value, %Symbol.dispose%)。
  3. 断言:kind 是 async-dispose。
  4. 令 asyncMethod 为 ? GetMethod(value, %Symbol.asyncDispose%)。
  5. 如果 asyncMethod 不是 undefined,则返回 asyncMethod。
  6. 令 syncMethod 为 ? GetMethod(value, %Symbol.dispose%)。
  7. 如果 syncMethod 是 undefined,则返回 undefined。
  8. 令 closure 为一个没有参数的新 Abstract Closure,它捕获 syncMethod,并在被调用时执行以下步骤:
    1. 令 obj 为 this 值。
    2. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
    3. 令 result 为 Completion(Call(syncMethod, obj))。
    4. IfAbruptRejectPromise(result, promiseCapability)。
    5. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « undefined »)。
    6. 返回 promiseCapability.[[Promise]]。
  9. 注:此函数对用户代码不可观察。它用于确保同步 %Symbol.dispose% 方法返回的 Promise 不会被 await,并且同步异常会被转换为被拒绝的 Promise。
  10. 返回 CreateBuiltinFunction(closure, 0, "", « »)。

7.5.5 DisposeResources ( disposableResourceStack, completion )

抽象操作 DisposeResources,接收参数 disposableResourceStack (列表 (元素:DisposableResource 记录)) 和 completion ((正常完成 (值:(ECMAScript 语言值 或 empty)) 或 突兀完成));返回值:(正常完成 (值:(ECMAScript 语言值 或 empty)) 或 突兀完成)。 调用时执行以下步骤:

  1. 令 needsAwait 为 false。
  2. 令 hasAwaited 为 false。
  3. 令 outputCompletion 为 completion。
  4. 对 disposableResourceStack 的每个元素 resource,按 List 的逆序执行
    1. 令 value 为 resource.[[ResourceValue]]。
    2. 令 kind 为 resource.[[Kind]]。
    3. 令 method 为 resource.[[DisposeMethod]]。
    4. 如果 kind 是 sync-dispose、needsAwait 是 true 且 hasAwaited 是 false,则
      1. 执行 ! Await(undefined)。
      2. 将 needsAwait 设置为 false。
    5. 如果 method 不是 undefined,则
      1. 令 result 为 Completion(Call(method, value))。
      2. 如果 result 是正常完成且 kind 是 async-dispose,则
        1. 将 result 设置为 Completion(Await(result.[[Value]]))。
        2. 将 hasAwaited 设置为 true。
      3. 如果 result 是抛出完成,则
        1. 如果 outputCompletion 是抛出完成,则
          1. 将 result 设置为 result.[[Value]]。
          2. 令 suppressed 为 outputCompletion.[[Value]]。
          3. 令 error 为新创建的 SuppressedError 对象。
          4. 执行 CreateNonEnumerableDataPropertyOrThrow(error, "error", result)。
          5. 执行 CreateNonEnumerableDataPropertyOrThrow(error, "suppressed", suppressed)。
          6. 将 outputCompletion 设置为 ThrowCompletion(error)。
        2. 否则,
          1. 将 outputCompletion 设置为 result。
    6. 否则,
      1. 断言:kind 是 async-dispose。
      2. 将 needsAwait 设置为 true。
      3. 注:这只能表示 await using 声明的初始化值为 null 或 undefined 的情况。
  5. 如果 needsAwait 是 true 且 hasAwaited 是 false,则
    1. 执行 ! Await(undefined)。
  6. 注:此时将永远不会再次使用 disposableResourceStack。实现可以丢弃 disposableResourceStack 的内容,例如通过垃圾回收。
  7. 返回 ? outputCompletion。