页面模式偏好

6 ECMAScript 数据类型和值

本规范中的算法操作各种值,每个值都有一个关联的类型。可能的值类型恰好就是本条款中定义的那些类型。类型进一步分为 ECMAScript 语言类型和规范类型。

6.1 ECMAScript 语言类型

ECMAScript 语言类型对应于 ECMAScript 程序员使用 ECMAScript 语言直接操作的值。ECMAScript 语言类型包括 Undefined、Null、Boolean、String、Symbol、Number、BigInt 和 Object。ECMAScript 语言值是由 ECMAScript 语言类型表征的值。

6.1.1 Undefined 类型

Undefined 类型恰好有一个值,称为 undefined。任何尚未赋值的变量都具有值 undefined。

6.1.2 Null 类型

Null 类型恰好有一个值,称为 null。

6.1.3 Boolean 类型

Boolean 类型表示具有两个值的逻辑实体,这两个值称为 true 和 false。

6.1.4 String 类型

String 类型是由零个或多个 16 位无符号整数值(“元素”)组成的所有有序序列的集合,最大长度为 253 - 1 个元素。String 类型通常用于表示正在运行的 ECMAScript 程序中的文本数据,在这种情况下,String 中的每个元素都被视为一个 UTF-16 码元值。每个元素都被视为占据序列中的一个位置。这些位置使用非负整数进行索引。第一个元素(如果有)位于索引 0,下一个元素(如果有)位于索引 1,依此类推。String 的长度是其中元素(即 16 位值)的数量。空 String 的长度为零,因此不包含任何元素。

不解释 String 内容的 ECMAScript 操作不会施加进一步的语义。解释 String 值的操作会将每个元素视为单个 UTF-16 码元。然而,ECMAScript 不限制这些码元的值或它们之间的关系,因此,进一步将 String 内容解释为以 UTF-16 编码的 Unicode 码点序列的操作必须考虑格式错误的子序列。此类操作会按照以下规则,对数值处于从 0xD800 到 0xDBFF 的闭区间中的每个码元(Unicode 标准将其定义为前导代理项,或更正式地称为高代理码元)以及数值处于从 0xDC00 到 0xDFFF 的闭区间中的每个码元(定义为尾随代理项,或更正式地称为低代理码元)进行特殊处理:

函数 String.prototype.normalize(参见 22.1.3.15)可用于显式规范化 String 值。String.prototype.localeCompare(参见 22.1.3.12)会在内部规范化 String 值,但其他操作都不会隐式规范化其所操作的字符串。除非另有说明,否则操作结果不区分语言和/或区域设置。

注

这种设计背后的理由是尽可能保持 String 实现的简单和高性能。如果 ECMAScript 源文本采用规范化形式 C,则只要字符串字面量不包含任何 Unicode 转义序列,就保证它们也经过规范化。

在本规范中,短语“A、B、... 的字符串连接”(其中每个参数都是 String 值、码元或码元序列)表示这样一个 String 值:其码元序列是按照各参数的顺序,将每个参数中的码元依次连接而成的。

短语“string 从 inclusiveStart 到 exclusiveEnd 的子字符串”(其中 string 是 String 值或码元序列,而 inclusiveStart 和 exclusiveEnd 是整数)表示由 string 中从索引 inclusiveStart 开始、到索引 exclusiveEnd 之前结束的连续码元组成的 String 值(当 inclusiveStart = exclusiveEnd 时为空 String)。如果省略“到”后缀,则使用 string 的长度作为 exclusiveEnd 的值。

短语“ASCII 单词字符”表示以下 String 值,它仅由 Unicode 基本拉丁区块中的所有字母和数字以及 U+005F(LOW LINE)组成:
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"。
由于历史原因,它对各种算法具有重要意义。

6.1.4.1 StringIndexOf ( string, searchValue, fromIndex )

抽象操作 StringIndexOf,接收参数 string (String)、searchValue (String) 和 fromIndex (非负整数);返回值:(非负整数 或 not-found)。 调用时执行以下步骤:

  1. 令 length 为 string 的长度。
  2. 如果 searchValue 是空 String 且 fromIndex ≤ length,则返回 fromIndex。
  3. 令 searchLength 为 searchValue 的长度。
  4. 对满足 fromIndex ≤ i ≤ length - searchLength 的每个整数 i,按升序执行
    1. 令 candidate 为 string 从 i 到 i + searchLength 的子字符串。
    2. 如果 candidate 是 searchValue,则返回 i。
  5. 返回 not-found。
注 1

如果 searchValue 是空 String 且 fromIndex ≤ string 的长度,则此算法返回 fromIndex。实际上,可以在字符串中的每个位置找到空 String,包括最后一个码元之后的位置。

注 2

如果 fromIndex + searchValue 的长度 > string 的长度,则此算法始终返回 not-found。

6.1.4.2 StringLastIndexOf ( string, searchValue, fromIndex )

抽象操作 StringLastIndexOf,接收参数 string (String)、searchValue (String) 和 fromIndex (非负整数);返回值:(非负整数 或 not-found)。 调用时执行以下步骤:

  1. 令 length 为 string 的长度。
  2. 令 searchLength 为 searchValue 的长度。
  3. 断言:fromIndex + searchLength ≤ length。
  4. 对满足 0 ≤ i ≤ fromIndex 的每个整数 i,按降序执行
    1. 令 candidate 为 string 从 i 到 i + searchLength 的子字符串。
    2. 如果 candidate 是 searchValue,则返回 i。
  5. 返回 not-found。
注

如果 searchValue 是空 String,则此算法返回 fromIndex。实际上,可以在字符串中的每个位置找到空 String,包括最后一个码元之后的位置。

6.1.5 Symbol 类型

Symbol 类型是所有可用作 Object 属性键的非 String 值的集合(6.1.7)。

每个 Symbol 都是唯一且不可变的。

每个 Symbol 都有一个不可变的 [[Description]] 内部槽,其值为 String 或 undefined。

6.1.5.1 知名 Symbol

知名 Symbol 是本规范算法明确引用的内置 Symbol 值。它们通常用作属性的键,而这些属性的值充当规范算法的扩展点。除非另有说明,否则所有 Realm 都共享知名 Symbol 值(9.3)。

在本规范中,使用标准内在对象表示法引用知名 Symbol,其中内在对象是 表 1 中列出的值之一。

注
本规范的早期版本使用 @@name 形式的表示法,而当前版本使用 %Symbol.name%。具体而言,曾使用以下名称:@@asyncIterator、@@hasInstance、@@isConcatSpreadable、@@iterator、@@match、@@matchAll、@@replace、@@search、@@species、@@split、@@toPrimitive、@@toStringTag 和 @@unscopables。
表 1: 知名 Symbol
规范名称 [[Description]] 值和用途
%Symbol.asyncDispose% "Symbol.asyncDispose" 在对象上异步执行资源清理的方法。当包含 AsyncDisposableStack 对象和 await using 声明的作用域完成求值时调用。
%Symbol.asyncIterator% "Symbol.asyncIterator" 返回对象默认异步迭代器的方法。由 for-await-of 语句的语义调用。
%Symbol.dispose% "Symbol.dispose" 在对象上执行显式资源清理的方法。当包含 DisposableStack 对象、AsyncDisposableStack 对象和 using 声明的作用域完成求值时调用。
%Symbol.hasInstance% "Symbol.hasInstance" 确定构造函数对象是否将某个对象识别为该构造函数实例之一的方法。由 instanceof 运算符的语义调用。
%Symbol.isConcatSpreadable% "Symbol.isConcatSpreadable" 一个 Boolean 值属性,如果为 true,则表示对象应由 Array.prototype.concat 展开为其数组元素。
%Symbol.iterator% "Symbol.iterator" 返回对象默认迭代器的方法。由 for-of 语句的语义调用。
%Symbol.match% "Symbol.match" 将正则表达式与字符串进行匹配的正则表达式方法。由 String.prototype.match 方法调用。
%Symbol.matchAll% "Symbol.matchAll" 返回一个迭代器、该迭代器生成正则表达式与字符串的匹配项的正则表达式方法。由 String.prototype.matchAll 方法调用。
%Symbol.replace% "Symbol.replace" 替换字符串中匹配子字符串的正则表达式方法。由 String.prototype.replace 方法调用。
%Symbol.search% "Symbol.search" 返回字符串中与正则表达式匹配位置的索引的正则表达式方法。由 String.prototype.search 方法调用。
%Symbol.species% "Symbol.species" 一个函数值属性,该函数是用于创建派生对象的构造函数。
%Symbol.split% "Symbol.split" 在与正则表达式匹配的索引位置拆分字符串的正则表达式方法。由 String.prototype.split 方法调用。
%Symbol.toPrimitive% "Symbol.toPrimitive" 将对象转换为相应原始值的方法。由 ToPrimitive 抽象操作调用。
%Symbol.toStringTag% "Symbol.toStringTag" 一个 String 值属性,用于创建对象的默认字符串描述。由内置方法 Object.prototype.toString 访问。
%Symbol.unscopables% "Symbol.unscopables" 一个对象值属性,其自有和继承属性名称是从关联对象的 with 环境绑定中排除的属性名称。

6.1.6 数值类型

ECMAScript 有两个内置数值类型:Number 和 BigInt。下面的抽象操作定义在这些数值类型之上。“结果”列显示返回类型,并指明该操作的某些调用是否可能返回突然完成。

表 2: 数值类型操作
操作 示例源代码 由以下项的 Evaluation 语义调用 ... 结果
Number::unaryMinus -x 一元 - 运算符 Number
BigInt::unaryMinus BigInt
Number::bitwiseNOT ~x 按位 NOT 运算符( ~ ) Number
BigInt::bitwiseNOT BigInt
Number::exponentiate x ** y 指数运算符 和 Math.pow ( base, exponent ) Number
BigInt::exponentiate 包含 BigInt 的正常完成或抛出完成
Number::multiply x * y 乘法运算符 Number
BigInt::multiply BigInt
Number::divide x / y 乘法运算符 Number
BigInt::divide 包含 BigInt 的正常完成或抛出完成
Number::remainder x % y 乘法运算符 Number
BigInt::remainder 包含 BigInt 的正常完成或抛出完成
Number::add x ++
++ x
x + y
后缀递增运算符、 前缀递增运算符 和 加法运算符( + ) Number
BigInt::add BigInt
Number::subtract x --
-- x
x - y
后缀递减运算符、 前缀递减运算符 和 减法运算符( - ) Number
BigInt::subtract BigInt
Number::leftShift x << y 左移运算符( << ) Number
BigInt::leftShift BigInt
Number::signedRightShift x >> y 有符号右移运算符( >> ) Number
BigInt::signedRightShift BigInt
Number::unsignedRightShift x >>> y 无符号右移运算符( >>> ) Number
BigInt::unsignedRightShift 抛出完成
Number::lessThan x < y
x > y
x <= y
x >= y
关系运算符, 通过 IsLessThan ( x, y, leftFirst ) Boolean 或 undefined(对于无序输入)
BigInt::lessThan Boolean
Number::equal x == y
x != y
x === y
x !== y
相等运算符, 通过 IsStrictlyEqual ( x, y ) Boolean
BigInt::equal
Number::sameValue Object.is(x, y) Object 内部方法, 通过 SameValue ( x, y ), 用于测试精确值相等性 Boolean
Number::sameValueZero [x].includes(y) 通过 SameValueZero ( x, y ), 用于测试值相等性,忽略 +0𝔽 与 -0𝔽 之间的差异,如 Array、Map 和 Set 方法中所用 Boolean
Number::bitwiseAND x & y 二元按位运算符 Number
BigInt::bitwiseAND BigInt
Number::bitwiseXOR x ^ y Number
BigInt::bitwiseXOR BigInt
Number::bitwiseOR x | y Number
BigInt::bitwiseOR BigInt
Number::toString String(x) 许多表达式和内置函数,通过 ToString ( arg ) String
BigInt::toString

由于这些数值类型通常无法在不损失精度或截断的情况下相互转换,因此 ECMAScript 语言不提供这些类型之间的隐式转换。当调用需要另一种类型的函数时,程序员必须显式调用 Number 和 BigInt 函数在类型之间进行转换。

注

ECMAScript 第一版及后续版本曾为某些运算符提供可能损失精度或发生截断的隐式数值转换。为了向后兼容,这些遗留隐式转换仍然保留,但没有为 BigInt 提供,以尽量减少程序员出错的机会,并为未来版本引入通用值类型保留可能性。

6.1.6.1 Number 类型

Number 类型恰好有 18,437,736,874,454,810,627 个(即 264 - 253 + 3)值,表示 IEEE 浮点算术标准中规定的双精度浮点 IEEE 754-2019 binary64 值,但 IEEE 标准中 9,007,199,254,740,990 个(即 253 - 2)不同的 NaN 值在 ECMAScript 中表示为单个特殊的 NaN 值。(请注意,NaN 值由程序表达式 NaN 产生。)在某些实现中,外部代码或许能够检测出不同 NaN 值之间的差异,但这种行为是实现定义的;对于 ECMAScript 代码而言,所有 NaN 值彼此无法区分。

注

将一个 Number 值存储到 ArrayBuffer(参见 25.1)或 SharedArrayBuffer(参见 25.2)后可能观察到的位模式,不一定与 ECMAScript 实现所使用的该 Number 值的内部表示相同。

还有另外两个特殊值,称为正无穷和负无穷。为简洁起见,在说明中也分别使用符号 +∞𝔽 和 -∞𝔽 来指代这些值。(请注意,这两个无穷 Number 值分别由程序表达式 +Infinity(或简称 Infinity)和 -Infinity 产生。)

其余 18,437,736,874,454,810,624 个(即 264 - 253)值中的每一个都是有限 Number。其中一半是正数,另一半是负数;对于每个正的有限 Number,都有一个大小相同的对应负 Number。

请注意,同时存在正零和负零。为简洁起见,在说明中也分别使用符号 +0𝔽 和 -0𝔽 来指代这些值。(请注意,这两个不同的零 Number 值分别由程序表达式 +0(或简称 0)和 -0 产生。)

18,437,736,874,454,810,622 个(即 264 - 253 - 2)有限非零值分为两类:

其中 18,428,729,675,200,069,632 个(即 264 - 254)是规格化的,形式为

s × m × 2e

其中 s 为 1 或 -1,m 是从 252(含)到 253(不含)区间内的整数,而 e 是从 -1074 到 971(两端均含)区间内的整数。

其余 9,007,199,254,740,990 个(即 253 - 2)值是非规格化的,形式为

s × m × 2e

其中 s 为 1 或 -1,m 是从 0(不含)到 252(不含)区间内的整数,而 e 为 -1074。

请注意,所有绝对值不大于 253 的正整数和负整数都可以在 Number 类型中表示。整数 0 在 Number 类型中有两种表示:+0𝔽 和 -0𝔽。

如果一个有限 Number 非零,并且用于表示它(采用上述两种形式之一)的整数 m 是奇数,则该有限 Number 具有奇数有效数。否则,它具有偶数有效数。

在本规范中,短语“x 的Number 值”,其中 x 表示一个精确的实数数学量(甚至可能是诸如 π 这样的无理数),是指按以下方式选出的一个 Number 值。考虑这样一个集合:由除 -0𝔽 之外的所有有限 Number 与两个不能在 Number 类型中表示的附加值的并集组成,这两个值分别是 21024(即 +1 × 253 × 2971)和 -21024(即 -1 × 253 × 2971)。选择该集合中数值最接近 x 的成员。如果集合中有两个值与 x 同样接近,则选择具有偶数有效数的那个;为此,这两个附加值 21024 和 -21024 被视为具有偶数有效数。最后,如果选择了 21024,则将其替换为 +∞𝔽;如果选择了 -21024,则将其替换为 -∞𝔽;如果选择了 +0𝔽,当且仅当 x < 0 时将其替换为 -0𝔽;其他任何选中的值均保持不变。所得结果就是 x 的 Number 值。(此过程与 IEEE 754-2019 roundTiesToEven 模式的行为完全对应。)

+∞ 的 Number 值是 +∞𝔽,而 -∞ 的 Number 值是 -∞𝔽。

某些 ECMAScript 运算符仅处理特定范围内的整数,例如从 -231 到 231 - 1 的闭区间,或从 0 到 216 - 1 的闭区间。这些运算符接受 Number 类型的任意值,但会先将每个此类值转换为预期范围内的整数值。请参见 7.1 中对数值转换操作的描述。

6.1.6.1.1 Number::unaryMinus ( number )

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

  1. 如果 number 是 NaN,则返回 NaN。
  2. 返回 number 的相反数;即计算一个大小相同但符号相反的 Number。

6.1.6.1.2 Number::bitwiseNOT ( number )

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

  1. 令 oldValue 为 ! ToInt32(number)。
  2. 返回 oldValue 的按位补码。结果的数学值可以精确表示为 32 位二进制补码位串。

6.1.6.1.3 Number::exponentiate ( base, exponent )

抽象操作 Number::exponentiate,接收参数 base (Number) 和 exponent (Number);返回值:Number。 它返回一个实现近似值,表示 base 的 exponent 次幂的结果。 调用时执行以下步骤:

  1. 如果 exponent 是 NaN,返回 NaN。
  2. 如果 exponent 是 +0𝔽 或 -0𝔽,返回 1𝔽。
  3. 如果 base 是 NaN,返回 NaN。
  4. 如果 base 是 +∞𝔽,那么
    1. 如果 exponent > +0𝔽,返回 +∞𝔽。
    2. 返回 +0𝔽。
  5. 如果 base 是 -∞𝔽,那么
    1. 如果 exponent > +0𝔽,那么
      1. 如果 exponent 是奇数整数 Number,返回 -∞𝔽。
      2. 返回 +∞𝔽。
    2. 如果 exponent 是奇数整数 Number,返回 -0𝔽。
    3. 返回 +0𝔽。
  6. 如果 base 是 +0𝔽,那么
    1. 如果 exponent > +0𝔽,返回 +0𝔽。
    2. 返回 +∞𝔽。
  7. 如果 base 是 -0𝔽,那么
    1. 如果 exponent > +0𝔽,那么
      1. 如果 exponent 是奇数整数 Number,返回 -0𝔽。
      2. 返回 +0𝔽。
    2. 如果 exponent 是奇数整数 Number,返回 -∞𝔽。
    3. 返回 +∞𝔽。
  8. 断言:base 是有限 Number,且既不是 +0𝔽 也不是 -0𝔽。
  9. 如果 exponent 是 +∞𝔽,那么
    1. 如果 abs(ℝ(base)) > 1,返回 +∞𝔽。
    2. 如果 abs(ℝ(base)) = 1,返回 NaN。
    3. 返回 +0𝔽。
  10. 如果 exponent 是 -∞𝔽,那么
    1. 如果 abs(ℝ(base)) > 1,返回 +0𝔽。
    2. 如果 abs(ℝ(base)) = 1,返回 NaN。
    3. 返回 +∞𝔽。
  11. 断言:exponent 是有限 Number,且既不是 +0𝔽 也不是 -0𝔽。
  12. 如果 base < -0𝔽 且 exponent 不是整数 Number,返回 NaN。
  13. 返回一个由实现近似得到的 Number 值,该值表示将 ℝ(base) 提升到 ℝ(exponent) 次幂所得的结果。
注

当 base 为 1𝔽 或 -1𝔽 且 exponent 为 +∞𝔽 或 -∞𝔽,或者当 base 为 1𝔽 且 exponent 为 NaN 时,base ** exponent 的结果与 IEEE 754-2019 不同。ECMAScript 第一版规定此操作的结果为 NaN,而 IEEE 754 后续修订版规定为 1𝔽。出于兼容性原因,保留了 ECMAScript 的历史行为。

6.1.6.1.4 Number::multiply ( x, y )

抽象操作 Number::multiply,接收参数 x (Number) 和 y (Number);返回值:Number。 它按照 IEEE 754-2019 二进制双精度算术的规则执行乘法,生成 x 和 y 的乘积。 调用时执行以下步骤:

  1. 如果 x 是 NaN 或 y 是 NaN,则返回 NaN。
  2. 如果 x 是 +∞𝔽 或 -∞𝔽,则
    1. 如果 y 是 +0𝔽 或 -0𝔽,则返回 NaN。
    2. 如果 y > +0𝔽,则返回 x。
    3. 返回 -x。
  3. 如果 y 是 +∞𝔽 或 -∞𝔽,则
    1. 如果 x 是 +0𝔽 或 -0𝔽,则返回 NaN。
    2. 如果 x > +0𝔽,则返回 y。
    3. 返回 -y。
  4. 如果 x 是 -0𝔽,则
    1. 如果 y 是 -0𝔽 或 y < -0𝔽,则返回 +0𝔽。
    2. 返回 -0𝔽。
  5. 如果 y 是 -0𝔽,则
    1. 如果 x < -0𝔽,则返回 +0𝔽。
    2. 返回 -0𝔽。
  6. 返回 𝔽(ℝ(x) × ℝ(y))。
注

有限精度乘法满足交换律,但并不总是满足结合律。

6.1.6.1.5 Number::divide ( x, y )

抽象操作 Number::divide,接收参数 x (Number) 和 y (Number);返回值:Number。 它按照 IEEE 754-2019 二进制双精度算术的规则执行除法,生成 x 与 y 的商,其中 x 是被除数,y 是除数。 调用时执行以下步骤:

  1. 如果 x 是 NaN 或 y 是 NaN,则返回 NaN。
  2. 如果 x 是 +∞𝔽 或 -∞𝔽,则
    1. 如果 y 是 +∞𝔽 或 -∞𝔽,则返回 NaN。
    2. 如果 y 是 +0𝔽 或 y > +0𝔽,则返回 x。
    3. 返回 -x。
  3. 如果 y 是 +∞𝔽,则
    1. 如果 x 是 +0𝔽 或 x > +0𝔽,则返回 +0𝔽。
    2. 返回 -0𝔽。
  4. 如果 y 是 -∞𝔽,则
    1. 如果 x 是 +0𝔽 或 x > +0𝔽,则返回 -0𝔽。
    2. 返回 +0𝔽。
  5. 如果 x 是 +0𝔽 或 -0𝔽,则
    1. 如果 y 是 +0𝔽 或 -0𝔽,则返回 NaN。
    2. 如果 y > +0𝔽,则返回 x。
    3. 返回 -x。
  6. 如果 y 是 +0𝔽,则
    1. 如果 x > +0𝔽,则返回 +∞𝔽。
    2. 返回 -∞𝔽。
  7. 如果 y 是 -0𝔽,则
    1. 如果 x > +0𝔽,则返回 -∞𝔽。
    2. 返回 +∞𝔽。
  8. 返回 𝔽(ℝ(x) / ℝ(y))。

6.1.6.1.6 Number::remainder ( numerator, denominator )

抽象操作 Number::remainder,接收参数 numerator (Number) 和 denominator (Number);返回值:Number。 它产生其操作数隐含除法所得的余数,其中 numerator 是被除数,denominator 是除数。 调用时执行以下步骤:

  1. 如果 numerator 是 NaN 或 denominator 是 NaN,返回 NaN。
  2. 如果 numerator 是 +∞𝔽 或 -∞𝔽,返回 NaN。
  3. 如果 denominator 是 +∞𝔽 或 -∞𝔽,返回 numerator。
  4. 如果 denominator 是 +0𝔽 或 -0𝔽,返回 NaN。
  5. 如果 numerator 是 +0𝔽 或 -0𝔽,返回 numerator。
  6. 断言:numerator 是有限 Number,且既不是 +0𝔽 也不是 -0𝔽。
  7. 断言:denominator 是有限 Number,且既不是 +0𝔽 也不是 -0𝔽。
  8. 令 quotient 为 ℝ(numerator) / ℝ(denominator)。
  9. 令 truncatedQuotient 为 truncate(quotient)。
  10. 令 remainder 为 ℝ(numerator) - (ℝ(denominator) × truncatedQuotient)。
  11. 如果 remainder = 0 且 numerator < -0𝔽,返回 -0𝔽。
  12. 返回 𝔽(remainder)。
注 1

在 C 和 C++ 中,余数运算符仅接受整数操作数;在 ECMAScript 中,它也接受浮点操作数。

注 2
由 % 运算符计算的浮点余数运算结果与 IEEE 754-2019 定义的“余数”运算不同。IEEE 754-2019 的“余数”运算根据舍入除法计算余数,而不是截断除法,因此其行为与通常的 integer 余数运算符并不类似。相反,ECMAScript 语言将浮点运算上的 % 定义为以类似 Java integer 余数运算符的方式运行;可将其与 C 库函数 fmod 进行比较。

6.1.6.1.7 Number::add ( x, y )

抽象操作 Number::add,接收参数 x (Number) 和 y (Number);返回值:Number。 它按照 IEEE 754-2019 二进制双精度算术的规则执行加法,生成其参数之和。 调用时执行以下步骤:

  1. 如果 x 是 NaN 或 y 是 NaN,返回 NaN。
  2. 如果 x 是 +∞𝔽 且 y 是 -∞𝔽,返回 NaN。
  3. 如果 x 是 -∞𝔽 且 y 是 +∞𝔽,返回 NaN。
  4. 如果 x 是 +∞𝔽 或 -∞𝔽,返回 x。
  5. 如果 y 是 +∞𝔽 或 -∞𝔽,返回 y。
  6. 断言:x 和 y 是有限 Number。
  7. 如果 x 是 -0𝔽 且 y 是 -0𝔽,返回 -0𝔽。
  8. 返回 𝔽(ℝ(x) + ℝ(y))。
注

有限精度加法满足交换律,但并不总是满足结合律。

6.1.6.1.8 Number::subtract ( x, y )

抽象操作 Number::subtract,接收参数 x (Number) 和 y (Number);返回值:Number。 它执行减法,生成操作数之差;x 是被减数,y 是减数。 调用时执行以下步骤:

  1. 返回 Number::add(x, Number::unaryMinus(y))。
注

x - y 始终产生与 x + (-y) 相同的结果。

6.1.6.1.9 Number::leftShift ( x, y )

抽象操作 Number::leftShift,接收参数 x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 令 leftNumber 为 ! ToInt32(x)。
  2. 令 rightNumber 为 ! ToUint32(y)。
  3. 令 shiftCount 为 ℝ(rightNumber) modulo 32。
  4. 返回将 leftNumber 左移 shiftCount 位的结果。结果的数学值可以精确表示为 32 位二进制补码位串。

6.1.6.1.10 Number::signedRightShift ( x, y )

抽象操作 Number::signedRightShift,接收参数 x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 令 leftNumber 为 ! ToInt32(x)。
  2. 令 rightNumber 为 ! ToUint32(y)。
  3. 令 shiftCount 为 ℝ(rightNumber) modulo 32。
  4. 返回对 leftNumber 执行符号扩展右移 shiftCount 位的结果。最高有效位会被传播。结果的数学值可以精确表示为 32 位二进制补码位串。

6.1.6.1.11 Number::unsignedRightShift ( x, y )

抽象操作 Number::unsignedRightShift,接收参数 x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 令 leftNumber 为 ! ToUint32(x)。
  2. 令 rightNumber 为 ! ToUint32(y)。
  3. 令 shiftCount 为 ℝ(rightNumber) modulo 32。
  4. 返回对 leftNumber 执行零填充右移 shiftCount 位的结果。空出的位用零填充。结果的数学值可以精确表示为 32 位无符号位串。

6.1.6.1.12 Number::lessThan ( x, y )

抽象操作 Number::lessThan,接收参数 x (Number) 和 y (Number);返回值:(Boolean 或 undefined)。 调用时执行以下步骤:

  1. 如果 x 是 NaN,返回 undefined。
  2. 如果 y 是 NaN,返回 undefined。
  3. 如果 x 是 y,返回 false。
  4. 如果 x 是 +0𝔽 且 y 是 -0𝔽,返回 false。
  5. 如果 x 是 -0𝔽 且 y 是 +0𝔽,返回 false。
  6. 如果 x 是 +∞𝔽,返回 false。
  7. 如果 y 是 +∞𝔽,返回 true。
  8. 如果 y 是 -∞𝔽,返回 false。
  9. 如果 x 是 -∞𝔽,返回 true。
  10. 断言:x 和 y 是有限 Number。
  11. 如果 ℝ(x) < ℝ(y),返回 true。
  12. 返回 false。

6.1.6.1.13 Number::equal ( x, y )

抽象操作 Number::equal,接收参数 x (Number) 和 y (Number);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 x 是 NaN,则返回 false。
  2. 如果 y 是 NaN,则返回 false。
  3. 如果 x 是 y,则返回 true。
  4. 如果 x 是 +0𝔽 且 y 是 -0𝔽,则返回 true。
  5. 如果 x 是 -0𝔽 且 y 是 +0𝔽,则返回 true。
  6. 返回 false。

6.1.6.1.14 Number::sameValue ( x, y )

抽象操作 Number::sameValue,接收参数 x (Number) 和 y (Number);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 x 是 NaN 且 y 是 NaN,则返回 true。
  2. 如果 x 是 +0𝔽 且 y 是 -0𝔽,则返回 false。
  3. 如果 x 是 -0𝔽 且 y 是 +0𝔽,则返回 false。
  4. 如果 x 是 y,则返回 true。
  5. 返回 false。

6.1.6.1.15 Number::sameValueZero ( x, y )

抽象操作 Number::sameValueZero,接收参数 x (Number) 和 y (Number);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 x 是 NaN 且 y 是 NaN,则返回 true。
  2. 如果 x 是 +0𝔽 且 y 是 -0𝔽,则返回 true。
  3. 如果 x 是 -0𝔽 且 y 是 +0𝔽,则返回 true。
  4. 如果 x 是 y,则返回 true。
  5. 返回 false。

6.1.6.1.16 NumberBitwiseOp ( op, x, y )

抽象操作 NumberBitwiseOp,接收参数 op ((&、^ 或 |))、x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 令 leftNumber 为 ! ToInt32(x)。
  2. 令 rightNumber 为 ! ToInt32(y)。
  3. 令 leftBits 为表示 ℝ(leftNumber) 的 32 位二进制补码位串。
  4. 令 rightBits 为表示 ℝ(rightNumber) 的 32 位二进制补码位串。
  5. 如果 op 是 &,则
    1. 令 result 为对 leftBits 和 rightBits 应用按位 AND 操作的结果。
  6. 否则如果 op 是 ^,则
    1. 令 result 为对 leftBits 和 rightBits 应用按位异或(XOR)操作的结果。
  7. 否则,
    1. 断言:op 是 |。
    2. 令 result 为对 leftBits 和 rightBits 应用按位包含 OR 操作的结果。
  8. 返回由 32 位二进制补码位串 result 表示的整数所对应的 Number 值。

6.1.6.1.17 Number::bitwiseAND ( x, y )

抽象操作 Number::bitwiseAND,接收参数 x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 返回 NumberBitwiseOp(&, x, y)。

6.1.6.1.18 Number::bitwiseXOR ( x, y )

抽象操作 Number::bitwiseXOR,接收参数 x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 返回 NumberBitwiseOp(^, x, y)。

6.1.6.1.19 Number::bitwiseOR ( x, y )

抽象操作 Number::bitwiseOR,接收参数 x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 返回 NumberBitwiseOp(|, x, y)。

6.1.6.1.20 Number::toString ( x, radix )

抽象操作 Number::toString,接收参数 x (Number) 和 radix (an integer in the inclusive interval from 2 to 36);返回值:String。 它使用基数为 radix 的位置记数系统将 x 表示为 String。使用基数 r 表示数字时所用的数字,按顺序取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个码元。大小大于或等于 1𝔽 的数字表示中绝不会包含前导零。 调用时执行以下步骤:

  1. 如果 x 是 NaN,则返回 "NaN"。
  2. 如果 x 是 +0𝔽 或 -0𝔽,则返回 "0"。
  3. 如果 x < -0𝔽,则返回 "-" 与 Number::toString(-x, radix) 的字符串连接。
  4. 如果 x 是 +∞𝔽,则返回 "Infinity"。
  5. 令 n、k 和 s 为满足以下条件的整数:k ≥ 1,radixk - 1 ≤ s < radixk,𝔽(s × radixn - k) 是 x,并且 k 尽可能小。注意,k 是使用基数 radix 表示 s 时的位数,s 不能被 radix 整除,并且这些条件不一定唯一确定 s 的最低有效位。
  6. 如果 radix ≠ 10 或 n 位于从 -5 到 21 的闭区间中,则
    1. 如果 n ≥ k,则
      1. 返回以下各项的字符串连接:
        • 使用基数 radix 表示 s 时的 k 个数字的码元
        • n - k 个码元 0x0030(DIGIT ZERO)
    2. 如果 n > 0,则
      1. 返回以下各项的字符串连接:
        • 使用基数 radix 表示 s 时最高有效的 n 个数字的码元
        • 码元 0x002E(FULL STOP)
        • 使用基数 radix 表示 s 时剩余 k - n 个数字的码元
    3. 断言:n ≤ 0。
    4. 返回以下各项的字符串连接:
      • 码元 0x0030(DIGIT ZERO)
      • 码元 0x002E(FULL STOP)
      • -n 个码元 0x0030(DIGIT ZERO)
      • 使用基数 radix 表示 s 时的 k 个数字的码元
  7. 注:在这种情况下,输入将使用科学 E 记数法表示,例如 1.2e+3。
  8. 断言:radix 是 10。
  9. 如果 n < 0,则
    1. 令 exponentSign 为码元 0x002D(HYPHEN-MINUS)。
  10. 否则,
    1. 令 exponentSign 为码元 0x002B(PLUS SIGN)。
  11. 如果 k = 1,则
    1. 返回以下各项的字符串连接:
      • s 的唯一数字的码元
      • 码元 0x0065(LATIN SMALL LETTER E)
      • exponentSign
      • abs(n - 1) 的十进制表示的码元
  12. 返回以下各项的字符串连接:
    • s 的十进制表示中最高有效数字的码元
    • 码元 0x002E(FULL STOP)
    • s 的十进制表示中剩余 k - 1 个数字的码元
    • 码元 0x0065(LATIN SMALL LETTER E)
    • exponentSign
    • abs(n - 1) 的十进制表示的码元
注 1

以下观察结果可作为实现的有用指南,但不属于本标准的规范性要求:

  • 如果 x 是除 -0𝔽 以外的任意 Number 值,则 ToNumber(ToString(x)) 是 x。
  • s 的最低有效数字并不总能由步骤 5 中列出的要求唯一确定。
注 2

对于提供比上述规则所要求更精确转换的实现,建议使用步骤 5 的以下替代版本作为指南:

  1. 令 n、k 和 s 为满足以下条件的整数:k ≥ 1,radixk - 1 ≤ s < radixk,𝔽(s × radixn - k) 是 x,并且 k 尽可能小。如果 s 有多个可能值,则选择使 s × radixn - k 最接近 ℝ(x) 的 s。如果存在两个这样的 s 值,则选择偶数的那个。注意,k 是使用基数 radix 表示 s 时的位数,并且 s 不能被 radix 整除。
注 3

ECMAScript 实现者可能会发现 David M. Gay 编写的有关浮点数二进制到十进制转换的论文和代码很有用:

Gay, David M. 正确舍入的二进制-十进制和十进制-二进制转换。数值分析,手稿 90-10。AT&T 贝尔实验室(新泽西州默里山)。1990 年 11 月 30 日。可从以下位置获取
https://ampl.com/_archive/first-website/REFS/rounding.pdf。相关代码可从以下位置获取
http://netlib.sandia.gov/fp/dtoa.c 和
http://netlib.sandia.gov/fp/g_fmt.c,也可以在各个 netlib 镜像站点找到。

6.1.6.2 BigInt 类型

BigInt 类型表示整数值。该值可以具有任意大小,不受特定位宽限制。一般而言,除非另有说明,各项操作都被设计为返回数学上精确的结果。对于二元操作,BigInt 的行为类似二进制补码字符串,负数被视为其左侧无限多个位均已置位。

6.1.6.2.1 BigInt::unaryMinus ( bigint )

抽象操作 BigInt::unaryMinus,接收参数 bigint (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 如果 bigint = 0ℤ,则返回 0ℤ。
  2. 返回 -bigint。

6.1.6.2.2 BigInt::bitwiseNOT ( bigint )

抽象操作 BigInt::bitwiseNOT,接收参数 bigint (BigInt);返回值:BigInt。 它返回 bigint 的反码。 调用时执行以下步骤:

  1. 返回 -bigint - 1ℤ。

6.1.6.2.3 BigInt::exponentiate ( base, exponent )

抽象操作 BigInt::exponentiate,接收参数 base (BigInt) 和 exponent (BigInt);返回值:(正常完成 (值:BigInt) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 exponent < 0ℤ,则抛出 RangeError 异常。
  2. 如果 base = 0ℤ 且 exponent = 0ℤ,则返回 1ℤ。
  3. 返回 base 的 exponent 次幂。

6.1.6.2.4 BigInt::multiply ( x, y )

抽象操作 BigInt::multiply,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 x × y。
注
即使结果的位宽远大于输入,也会给出精确的数学结果。

6.1.6.2.5 BigInt::divide ( x, y )

抽象操作 BigInt::divide,接收参数 x (BigInt) 和 y (BigInt);返回值:(正常完成 (值:BigInt) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 y = 0ℤ,则抛出 RangeError 异常。
  2. 令 quotient 为 ℝ(x) / ℝ(y)。
  3. 返回 ℤ(truncate(quotient))。

6.1.6.2.6 BigInt::remainder ( numerator, denominator )

抽象操作 BigInt::remainder,接收参数 numerator (BigInt) 和 denominator (BigInt);返回值:(正常完成 (值:BigInt) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 denominator = 0ℤ,则抛出 RangeError 异常。
  2. 如果 numerator = 0ℤ,则返回 0ℤ。
  3. 令 quotient 为 ℝ(numerator) / ℝ(denominator)。
  4. 令 truncatedQuotient 为 ℤ(truncate(quotient))。
  5. 返回 numerator - (denominator × truncatedQuotient)。
注
结果的符号与被除数的符号相同。

6.1.6.2.7 BigInt::add ( x, y )

抽象操作 BigInt::add,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 x + y。

6.1.6.2.8 BigInt::subtract ( x, y )

抽象操作 BigInt::subtract,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 x - y。

6.1.6.2.9 BigInt::leftShift ( x, y )

抽象操作 BigInt::leftShift,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 如果 y < 0ℤ,则
    1. 返回 ℤ(floor(ℝ(x) / 2-ℝ(y)))。
  2. 返回 x × 2ℤy。
注
此处的语义应等同于按位移位,将 BigInt 视为无限长度的二进制补码数字字符串。

6.1.6.2.10 BigInt::signedRightShift ( x, y )

抽象操作 BigInt::signedRightShift,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 BigInt::leftShift(x, -y)。

6.1.6.2.11 BigInt::unsignedRightShift ( x, y )

抽象操作 BigInt::unsignedRightShift,接收参数 x (BigInt) 和 y (BigInt);返回值:抛出完成。 调用时执行以下步骤:

  1. 抛出 TypeError 异常。

6.1.6.2.12 BigInt::lessThan ( x, y )

抽象操作 BigInt::lessThan,接收参数 x (BigInt) 和 y (BigInt);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 ℝ(x) < ℝ(y),则返回 true。
  2. 返回 false。

6.1.6.2.13 BigInt::equal ( x, y )

抽象操作 BigInt::equal,接收参数 x (BigInt) 和 y (BigInt);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 ℝ(x) = ℝ(y),则返回 true。
  2. 返回 false。

6.1.6.2.14 BinaryAnd ( x, y )

抽象操作 BinaryAnd,接收参数 x ((0 或 1)) 和 y ((0 或 1));返回值:(0 或 1)。 调用时执行以下步骤:

  1. 如果 x = 1 且 y = 1,则返回 1。
  2. 返回 0。

6.1.6.2.15 BinaryOr ( x, y )

抽象操作 BinaryOr,接收参数 x ((0 或 1)) 和 y ((0 或 1));返回值:(0 或 1)。 调用时执行以下步骤:

  1. 如果 x = 1 或 y = 1,则返回 1。
  2. 返回 0。

6.1.6.2.16 BinaryXor ( x, y )

抽象操作 BinaryXor,接收参数 x ((0 或 1)) 和 y ((0 或 1));返回值:(0 或 1)。 调用时执行以下步骤:

  1. 如果 x = 1 且 y = 0,则返回 1。
  2. 如果 x = 0 且 y = 1,则返回 1。
  3. 返回 0。

6.1.6.2.17 BigIntBitwiseOp ( op, x, y )

抽象操作 BigIntBitwiseOp,接收参数 op ((&、^ 或 |))、x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 将 x 设置为 ℝ(x)。
  2. 将 y 设置为 ℝ(y)。
  3. 令 result 为 0。
  4. 令 shift 为 0。
  5. 重复,直到 (x = 0 或 x = -1) 且 (y = 0 或 y = -1),
    1. 令 xDigit 为 x modulo 2。
    2. 令 yDigit 为 y modulo 2。
    3. 如果 op 是 &,则
      1. 将 result 设置为 result + 2shift × BinaryAnd(xDigit, yDigit)。
    4. 否则如果 op 是 |,则
      1. 将 result 设置为 result + 2shift × BinaryOr(xDigit, yDigit)。
    5. 否则,
      1. 断言:op 是 ^。
      2. 将 result 设置为 result + 2shift × BinaryXor(xDigit, yDigit)。
    6. 将 shift 设置为 shift + 1。
    7. 将 x 设置为 (x - xDigit) / 2。
    8. 将 y 设置为 (y - yDigit) / 2。
  6. 如果 op 是 &,则
    1. 令 signBit 为 BinaryAnd(x modulo 2, y modulo 2)。
  7. 否则如果 op 是 |,则
    1. 令 signBit 为 BinaryOr(x modulo 2, y modulo 2)。
  8. 否则,
    1. 断言:op 是 ^。
    2. 令 signBit 为 BinaryXor(x modulo 2, y modulo 2)。
  9. 如果 signBit ≠ 0,则
    1. 将 result 设置为 result - 2shift。
    2. 注:这会扩展符号。
  10. 返回 result 对应的 BigInt 值。

6.1.6.2.18 BigInt::bitwiseAND ( x, y )

抽象操作 BigInt::bitwiseAND,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 BigIntBitwiseOp(&, x, y)。

6.1.6.2.19 BigInt::bitwiseXOR ( x, y )

抽象操作 BigInt::bitwiseXOR,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 BigIntBitwiseOp(^, x, y)。

6.1.6.2.20 BigInt::bitwiseOR ( x, y )

抽象操作 BigInt::bitwiseOR,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 BigIntBitwiseOp(|, x, y)。

6.1.6.2.21 BigInt::toString ( x, radix )

抽象操作 BigInt::toString,接收参数 x (BigInt) 和 radix (an integer in the inclusive interval from 2 to 36);返回值:String。 它使用基数为 radix 的位置记数系统将 x 表示为 String。使用基数 r 表示 BigInt 时所用的数字,按顺序取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个码元。除 0ℤ 以外的 BigInt 表示中绝不会包含前导零。 调用时执行以下步骤:

  1. 如果 x < 0ℤ,则返回 "-" 与 BigInt::toString(-x, radix) 的字符串连接。
  2. 返回由使用基数 radix 表示 x 所组成的 String 值。

6.1.7 Object 类型

Object 类型的每个实例(也简称为“Object”)都表示属性的集合。每个属性要么是数据属性,要么是访问器属性:

  • 数据属性将一个键值与一个 ECMAScript 语言值及一组 Boolean 特性关联起来。
  • 访问器属性将一个键值与一个或两个访问器函数及一组 Boolean 特性关联起来。访问器函数用于存储或检索与该属性关联的 ECMAScript 语言值。

对象的属性使用属性键进行唯一标识。属性键是 String 或 Symbol。所有 String 和 Symbol(包括空 String)都可作为有效的属性键。属性名称是 String 类型的属性键。

整数索引是这样一个属性名称 n:CanonicalNumericIndexString(n) 返回从 +0𝔽 到 𝔽(253 - 1) 的闭区间中的整数 Number。数组索引是这样一个整数索引 n:CanonicalNumericIndexString(n) 返回从 +0𝔽 到 𝔽(232 - 2) 的闭区间中的整数 Number。

注

每个非负安全整数都有一个对应的整数索引。除了 232 - 1 之外,每个 32 位无符号整数都有一个对应的数组索引。"-0" 既不是整数索引,也不是数组索引。

属性键用于访问属性及其值。属性访问有两种:get 和 set,分别对应于值检索和赋值。可通过 get 和 set 访问的属性既包括作为对象直接组成部分的自有属性,也包括通过属性继承关系由另一个关联对象提供的继承属性。继承属性可以是该关联对象的自有属性或继承属性。对象的每个自有属性都必须具有与该对象其他自有属性的键值不同的键值。

在逻辑上,所有对象都是属性的集合,但存在多种形式的对象,它们在访问和操作自身属性的语义上有所不同。有关多种对象形式的定义,请参见 6.1.7.2。

此外,某些对象是可调用的;它们称为函数或函数对象,并将在下文进一步描述。ECMAScript 中的所有函数都是 Object 类型的成员。

6.1.7.1 属性特性

本规范使用特性来定义和说明 Object 属性的状态,如 表 3 所述。除非明确规定,否则每个特性的初始值都是其默认值。

表 3: Object 属性的特性
特性名称 存在该特性的属性类型 值域 默认值 描述
[[Value]] 数据属性 ECMAScript 语言值 undefined 对该属性执行 get 访问时检索到的值。
[[Writable]] 数据属性 Boolean false 如果为 false,ECMAScript 代码尝试使用 [[Set]] 更改该属性的 [[Value]] 特性将不会成功。
[[Getter]] 访问器属性 函数对象或 undefined undefined 如果值不是 undefined,则每当对该属性执行 get 访问时,都会使用空参数列表调用其 [[Call]] 内部方法(表 5)以检索属性值。
[[Setter]] 访问器属性 函数对象或 undefined undefined 如果值不是 undefined,则每当对该属性执行 set 访问时,都会使用一个仅包含所赋值的参数列表调用其 [[Call]] 内部方法(表 5)。属性的 [[Setter]] 内部方法产生的效果可能会影响该属性的 [[Getter]] 内部方法后续调用所返回的值,但并不要求必须如此。
[[Enumerable]] 数据属性或访问器属性 Boolean false 如果为 true,则该属性会由 for-in 枚举进行枚举(参见 14.7.5)。否则,称该属性为不可枚举。
[[Configurable]] 数据属性或访问器属性 Boolean false 如果为 false,则尝试删除该属性、将其从数据属性更改为访问器属性或从访问器属性更改为数据属性,或者对其特性进行任何更改(替换现有 [[Value]] 或将 [[Writable]] 设置为 false 除外)都会失败。

6.1.7.2 Object 内部方法和内部槽

在 ECMAScript 中,对象的实际语义通过称为内部方法的算法来规定。ECMAScript 引擎中的每个对象都与一组定义其运行时行为的内部方法相关联。这些内部方法不是 ECMAScript 语言的一部分。本规范定义它们纯粹是为了说明。然而,ECMAScript 实现中的每个对象都必须按照与其关联的内部方法所规定的方式运行。具体如何实现由实现自行确定。

内部方法名称是多态的。这意味着,当在不同对象值上调用同一个内部方法名称时,它们可能执行不同的算法。实际被调用内部方法的对象是该调用的“目标”。如果在运行时,算法的实现尝试使用某个对象不支持的内部方法,则抛出 TypeError 异常。

内部槽对应于与对象、Symbol 或 Private Name 关联并由各种 ECMAScript 规范算法使用的内部状态。内部槽不是对象属性,也不会被继承。根据具体的内部槽规范,此类状态可以由任何 ECMAScript 语言类型的值或特定 ECMAScript 规范类型的值组成。除非另有明确规定,否则内部槽会作为创建 Object、Symbol 或 Private Name 过程的一部分进行分配,并且不能动态添加。除非另有规定,否则内部槽的初始值为 undefined。本规范中的各种算法会创建具有内部槽的值。然而,ECMAScript 语言没有提供直接操作内部槽的方式。

所有对象都有一个名为 [[PrivateElements]] 的内部槽,它是 PrivateElements 的 List。此 List 表示对象的私有字段、方法和访问器的值。最初,它是空 List。

本规范使用双重方括号 [[ ]] 括起来的名称来标识内部方法和内部槽。

表 4 汇总了本规范使用的、适用于由 ECMAScript 代码创建或操作的所有对象的基本内部方法。每个对象都必须为所有基本内部方法提供算法。不过,并非所有对象都必须为这些方法使用相同的算法。

普通对象是满足以下所有条件的对象:

  • 对于 表 4 中列出的内部方法,对象使用 10.1 中定义的方法。
  • 如果对象具有 [[Call]] 内部方法,则使用 10.2.1 中定义的方法或 10.3.1 中定义的方法。
  • 如果对象具有 [[Construct]] 内部方法,则使用 10.2.2 中定义的方法或 10.3.2 中定义的方法。

异质对象是任何非普通对象的对象。

本规范根据对象的内部方法识别不同种类的异质对象。一个对象即使在行为上等同于某种特定的异质对象(例如 Array 异质对象或绑定函数异质对象),但如果它不具有为该种类规定的同一组内部方法,就不会被识别为该种类的异质对象。

表 4 和其他类似表格描述每个内部方法的调用模式。调用模式始终包含一个带括号的描述性参数名称列表。

除了其参数之外,内部方法始终可以访问作为方法调用目标的对象。

内部方法隐式返回 Completion Record,它要么是包装了调用模式中所示返回类型值的正常完成,要么是抛出完成。

表 4: 基本内部方法
内部方法 描述 定义
[[GetPrototypeOf]] ( )

内部方法 [[GetPrototypeOf]],接收无参数;返回值:(正常完成 (值:(Object 或 null)) 或 抛出完成)。

它确定为此对象提供继承属性的对象。null 值表示不存在这样的对象。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[SetPrototypeOf]] ( proto )

内部方法 [[SetPrototypeOf]],接收参数 proto ((Object 或 null));返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它将此对象与另一个提供继承属性的对象关联起来。传入 null 表示不存在提供继承属性的对象。返回 true 表示操作已成功完成,返回 false 表示操作未成功。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[IsExtensible]] ( )

内部方法 [[IsExtensible]],接收无参数;返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它确定是否允许向此对象添加其他属性。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[PreventExtensions]] ( )

内部方法 [[PreventExtensions]],接收无参数;返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它控制是否可以向此对象添加新属性。如果操作成功则返回 true,如果操作失败则返回 false。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[GetOwnProperty]] ( propertyKey )

内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:(属性描述符 或 undefined)) 或 抛出完成)。

它返回此对象中键为 propertyKey 的自有属性的 Property Descriptor;如果不存在这样的属性,则返回 undefined。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[DefineOwnProperty]] ( propertyKey, propertyDesc )

内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它创建或修改键为 propertyKey 的自有属性,使其具有 propertyDesc 所描述的状态。如果操作成功则返回 true;如果无法创建或更新该属性,则返回 false。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[HasProperty]] ( propertyKey )

内部方法 [[HasProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它返回一个 Boolean,指示此对象是否已经具有键为 propertyKey 的自有属性或继承属性。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[Get]] ( propertyKey, receiver )

内部方法 [[Get]],接收参数 propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。

它从此对象返回键为 propertyKey 的属性值。如果为了检索属性值必须执行任何 ECMAScript 代码,则在对代码求值时使用 receiver 作为 this 值。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[Set]] ( propertyKey, value, receiver )

内部方法 [[Set]],接收参数 propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它将键为 propertyKey 的属性值设置为 value。如果为了设置属性值必须执行任何 ECMAScript 代码,则在对代码求值时使用 receiver 作为 this 值。如果属性值已设置,则返回 true;如果无法设置,则返回 false。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[Delete]] ( propertyKey )

内部方法 [[Delete]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它从此对象中移除键为 propertyKey 的自有属性。如果该属性未被删除且仍然存在,则返回 false。如果该属性已被删除或不存在,则返回 true。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[OwnPropertyKeys]] ( )

内部方法 [[OwnPropertyKeys]],接收无参数;返回值:(正常完成 (值:列表 (元素:属性键)) 或 抛出完成)。

它返回一个 List,其元素是该对象的所有自有属性键。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:

表 5 汇总了可作为函数调用的对象所支持的其他基本内部方法。函数对象是支持 [[Call]] 内部方法的对象。构造函数是支持 [[Construct]] 内部方法的对象。每个支持 [[Construct]] 的对象都必须支持 [[Call]];也就是说,每个构造函数都必须是函数对象。因此,构造函数也可以称为构造函数函数或构造函数函数对象。

表 5: 函数对象的附加基本内部方法
内部方法 描述 定义
[[Call]] ( thisArg, argList )

内部方法 [[Call]],接收参数 thisArg (ECMAScript 语言值) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。

它执行与此对象关联的代码。通过函数调用表达式调用。传给内部方法的参数是一个 this 值和一个 List,该 List 的元素是调用表达式传给函数的参数。实现此内部方法的对象是可调用的。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[Construct]] ( argList, newTarget )

内部方法 [[Construct]],接收参数 argList (列表 (元素:ECMAScript 语言值)) 和 newTarget (构造函数);返回值:(正常完成 (值:Object) 或 抛出完成)。

它创建一个对象。通过 new 运算符或 super 调用来调用。内部方法的第一个参数是一个 List,其元素是构造函数调用或 super 调用的参数。第二个参数是最初应用 new 运算符的对象。实现此内部方法的对象称为构造函数。函数对象不一定是构造函数,此类非构造函数的函数对象没有 [[Construct]] 内部方法。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:

普通对象和标准异质对象的基本内部方法语义在条款 10 中规定。如果实现不支持对异质对象内部方法的任何规定用法,则尝试该用法时必须抛出 TypeError 异常。

6.1.7.3 基本内部方法的不变量

ECMAScript 引擎中 Object 的内部方法必须符合下面规定的不变量列表。普通 ECMAScript Object 以及本规范中的所有标准异质对象都保持这些不变量。ECMAScript Proxy 对象通过对 [[ProxyHandler]] 对象上调用的陷阱结果执行运行时检查来保持这些不变量。

任何由实现提供的异质对象也必须为这些对象保持这些不变量。违反这些不变量可能导致 ECMAScript 代码出现不可预测的行为并产生安全问题。但是,违反这些不变量绝不能损害实现的内存安全性。

实现不得以任何方式允许绕过这些不变量,例如提供实现基本内部方法功能、却不强制执行其不变量的替代接口。

定义:

  • 内部方法的目标是调用该内部方法的对象。
  • 如果已观察到目标的 [[IsExtensible]] 内部方法返回 false,或者其 [[PreventExtensions]] 内部方法返回 true,则该目标是不可扩展的。
  • 不存在的属性是不可扩展目标上不存在的自有属性。
  • 所有对 SameValue 的引用都按照 SameValue 算法的定义。

返回值:

任何内部方法返回的值都必须是 Completion Record,并且满足以下两种情况之一:

  • [[Type]] = normal、[[Target]] = empty,且 [[Value]] = 下方为该内部方法显示的“正常返回类型”的值,或
  • [[Type]] = throw、[[Target]] = empty,且 [[Value]] = 任意 ECMAScript 语言值。
注 1

内部方法不得返回 continue 完成、break 完成或 return 完成。

[[GetPrototypeOf]] ( )

  • 正常返回类型是 Object 或 Null。
  • 如果目标不可扩展,并且 [[GetPrototypeOf]] 返回值 proto,则以后对 [[GetPrototypeOf]] 的任何调用都应返回与 proto SameValue 的值。
注 2

对象的原型链应具有有限长度(也就是说,从任何对象开始,递归地对其结果应用 [[GetPrototypeOf]] 内部方法最终应得到值 null)。但是,如果原型链包含任何不使用 [[GetPrototypeOf]] 普通对象定义的异质对象,则无法将此要求作为对象级不变量强制执行。这样的循环原型链可能导致访问对象属性时出现无限循环。

[[SetPrototypeOf]] ( proto )

  • 正常返回类型是 Boolean。
  • 如果目标不可扩展,则 [[SetPrototypeOf]] 必须返回 false,除非 proto 与观察到的目标 [[GetPrototypeOf]] 值 SameValue。

[[IsExtensible]] ( )

  • 正常返回类型是 Boolean。
  • 如果 [[IsExtensible]] 返回 false,则以后在目标上对 [[IsExtensible]] 的所有调用都必须返回 false。

[[PreventExtensions]] ( )

  • 正常返回类型是 Boolean。
  • 如果 [[PreventExtensions]] 返回 true,则以后在目标上对 [[IsExtensible]] 的所有调用都必须返回 false,并且目标现在被视为不可扩展。

[[GetOwnProperty]] ( propertyKey )

  • 正常返回类型是 Property Descriptor 或 Undefined。
  • 如果返回值是 Property Descriptor,则它必须是完全填充的 Property Descriptor。
  • 如果 propertyKey 被描述为不可配置、不可写的自有数据属性,则以后对 [[GetOwnProperty]] ( propertyKey ) 的所有调用都必须返回其 [[Value]] 与 propertyKey 的 [[Value]] 特性 SameValue 的 Property Descriptor。
  • 如果 propertyKey 除 [[Writable]] 和 [[Value]] 之外的特性可能随时间变化,或者该属性可能被删除,则 propertyKey 的 [[Configurable]] 特性必须为 true。
  • 如果 [[Writable]] 特性可能从 false 更改为 true,则 [[Configurable]] 特性必须为 true。
  • 如果目标不可扩展且 propertyKey 不存在,则以后在目标上对 [[GetOwnProperty]] (propertyKey) 的所有调用都必须将 propertyKey 描述为不存在(即 [[GetOwnProperty]] (propertyKey) 必须返回 undefined)。
注 3

作为第三个不变量的结果,如果一个属性被描述为数据属性并且它可能随时间返回不同的值,则即使其他基本内部方法没有公开任何更改该值的机制,[[Writable]] 和 [[Configurable]] 特性中的一个或两个也必须为 true。

[[DefineOwnProperty]] ( propertyKey, propertyDesc )

  • 正常返回类型是 Boolean。
  • 如果之前已观察到 propertyKey 是目标的不可配置自有属性,则 [[DefineOwnProperty]] 必须返回 false,除非满足以下任一条件:
    1. propertyKey 是可写数据属性。不可配置的可写数据属性可以更改为不可配置的不可写数据属性。
    2. propertyDesc 的所有特性都与 propertyKey 的相应特性 SameValue。
  • 如果目标不可扩展,并且 propertyKey 是不存在的自有属性,则 [[DefineOwnProperty]] (propertyKey, propertyDesc) 必须返回 false。也就是说,不可扩展的目标对象不能通过新属性进行扩展。

[[HasProperty]] ( propertyKey )

  • 正常返回类型是 Boolean。
  • 如果之前观察到 propertyKey 是目标的不可配置自有数据属性或访问器属性,则 [[HasProperty]] 必须返回 true。

[[Get]] ( propertyKey, receiver )

  • 正常返回类型是任意 ECMAScript 语言类型。
  • 如果之前观察到 propertyKey 是目标上值为 value 的不可配置、不可写自有数据属性,则 [[Get]] 必须返回与 value SameValue 的值。
  • 如果之前观察到 propertyKey 是目标的不可配置自有访问器属性,且其 [[Getter]] 特性为 undefined,则 [[Get]] 操作必须返回 undefined。

[[Set]] ( propertyKey, value, receiver )

  • 正常返回类型是 Boolean。
  • 如果之前观察到 propertyKey 是目标的不可配置、不可写自有数据属性,则 [[Set]] 必须返回 false,除非 value 与 propertyKey 的 [[Value]] 特性 SameValue。
  • 如果之前观察到 propertyKey 是目标的不可配置自有访问器属性,且其 [[Setter]] 特性为 undefined,则 [[Set]] 操作必须返回 false。

[[Delete]] ( propertyKey )

  • 正常返回类型是 Boolean。
  • 如果之前观察到 propertyKey 是目标的不可配置自有数据属性或访问器属性,则 [[Delete]] 必须返回 false。

[[OwnPropertyKeys]] ( )

  • 正常返回类型是 List。
  • 返回的 List 不得包含任何重复条目。
  • 返回的 List 的每个元素都必须是属性键。
  • 返回的 List 至少必须包含之前观察到的所有不可配置自有属性的键。
  • 如果目标不可扩展,则返回的 List 必须且只能包含可使用 [[GetOwnProperty]] 观察到的目标所有自有属性的键。

[[Call]] ( )

[[Construct]] ( )

  • 正常返回类型是 Object。
  • 目标还必须具有 [[Call]] 内部方法。

6.1.7.4 知名内在对象

知名内在对象是本规范算法明确引用的内置对象,并且通常具有特定于 Realm 的标识。除非另有规定,否则每个内在对象实际上对应一组相似对象,每个 Realm 一个。

在本规范中,%name% 形式的引用表示与当前 Realm 关联、对应于该名称的内在对象。%name.a.b% 形式的引用表示:如同在任何 ECMAScript 代码求值之前访问内在对象 %name% 的 "a" 属性值的 "b" 属性。当前 Realm 及其内在对象的确定方式见 9.4。知名内在对象列于 表 6。

表 6: 知名内在对象
内在对象名称 全局名称 ECMAScript 语言关联
%AggregateError% "AggregateError" AggregateError 构造函数(20.5.7.1)
%Array% "Array" Array 构造函数(23.1.1)
%ArrayBuffer% "ArrayBuffer" ArrayBuffer 构造函数(25.1.4)
%ArrayIteratorPrototype% Array Iterator 对象的原型(23.1.5)
%AsyncDisposableStack% "AsyncDisposableStack" AsyncDisposableStack 构造函数(27.4.1)
%AsyncFromSyncIteratorPrototype% Async-from-Sync Iterator 对象的原型(27.1.5)
%AsyncFunction% 异步函数对象的构造函数(27.10.1)
%AsyncGeneratorFunction% 异步生成器函数对象的构造函数(27.7.1)
%AsyncGeneratorPrototype% 异步生成器对象的原型(27.9)
%AsyncIteratorPrototype% 所有标准内置异步迭代器对象都间接继承自的对象
%Atomics% "Atomics" Atomics 对象(25.4)
%BigInt% "BigInt" BigInt 构造函数(21.2.1)
%BigInt64Array% "BigInt64Array" BigInt64Array 构造函数(23.2)
%BigUint64Array% "BigUint64Array" BigUint64Array 构造函数(23.2)
%Boolean% "Boolean" Boolean 构造函数(20.3.1)
%DataView% "DataView" DataView 构造函数(25.3.2)
%Date% "Date" Date 构造函数(21.4.2)
%decodeURI% "decodeURI" decodeURI 函数(19.2.6.1)
%decodeURIComponent% "decodeURIComponent" decodeURIComponent 函数(19.2.6.2)
%DisposableStack% "DisposableStack" DisposableStack 构造函数(27.3.1)
%encodeURI% "encodeURI" encodeURI 函数(19.2.6.3)
%encodeURIComponent% "encodeURIComponent" encodeURIComponent 函数(19.2.6.4)
%Error% "Error" Error 构造函数(20.5.1)
%eval% "eval" eval 函数(19.2.1)
%EvalError% "EvalError" EvalError 构造函数(20.5.5.1)
%FinalizationRegistry% "FinalizationRegistry" FinalizationRegistry 构造函数(26.2.1)
%Float16Array% "Float16Array" Float16Array 构造函数(23.2)
%Float32Array% "Float32Array" Float32Array 构造函数(23.2)
%Float64Array% "Float64Array" Float64Array 构造函数(23.2)
%ForInIteratorPrototype% For-In Iterator 对象的原型(14.7.5.10)
%Function% "Function" Function 构造函数(20.2.1)
%GeneratorFunction% 生成器函数对象的构造函数(27.6.1)
%GeneratorPrototype% 生成器对象的原型(27.8)
%Int8Array% "Int8Array" Int8Array 构造函数(23.2)
%Int16Array% "Int16Array" Int16Array 构造函数(23.2)
%Int32Array% "Int32Array" Int32Array 构造函数(23.2)
%isFinite% "isFinite" isFinite 函数(19.2.2)
%isNaN% "isNaN" isNaN 函数(19.2.3)
%Iterator% "Iterator" Iterator 构造函数(27.1.3.1)
%IteratorHelperPrototype% Iterator Helper 对象的原型(27.1.2.1)
%JSON% "JSON" JSON 对象(25.5)
%Map% "Map" Map 构造函数(24.1.1)
%MapIteratorPrototype% Map Iterator 对象的原型(24.1.5)
%Math% "Math" Math 对象(21.3)
%Number% "Number" Number 构造函数(21.1.1)
%Object% "Object" Object 构造函数(20.1.1)
%parseFloat% "parseFloat" parseFloat 函数(19.2.4)
%parseInt% "parseInt" parseInt 函数(19.2.5)
%Promise% "Promise" Promise 构造函数(27.5.3)
%Proxy% "Proxy" Proxy 构造函数(28.2.1)
%RangeError% "RangeError" RangeError 构造函数(20.5.5.2)
%ReferenceError% "ReferenceError" ReferenceError 构造函数(20.5.5.3)
%Reflect% "Reflect" Reflect 对象(28.1)
%RegExp% "RegExp" RegExp 构造函数(22.2.4)
%RegExpStringIteratorPrototype% RegExp String Iterator 对象的原型(22.2.9)
%Set% "Set" Set 构造函数(24.2.2)
%SetIteratorPrototype% Set Iterator 对象的原型(24.2.6)
%SharedArrayBuffer% "SharedArrayBuffer" SharedArrayBuffer 构造函数(25.2.3)
%String% "String" String 构造函数(22.1.1)
%StringIteratorPrototype% String Iterator 对象的原型(22.1.5)
%SuppressedError% "SuppressedError" SuppressedError 构造函数(20.5.8.1)
%Symbol% "Symbol" Symbol 构造函数(20.4.1)
%SyntaxError% "SyntaxError" SyntaxError 构造函数(20.5.5.4)
%ThrowTypeError% 一个无条件抛出 %TypeError% 新实例的函数对象
%TypedArray% 所有类型化 Array 构造函数的超类(23.2.1)
%TypeError% "TypeError" TypeError 构造函数(20.5.5.5)
%Uint8Array% "Uint8Array" Uint8Array 构造函数(23.2)
%Uint8ClampedArray% "Uint8ClampedArray" Uint8ClampedArray 构造函数(23.2)
%Uint16Array% "Uint16Array" Uint16Array 构造函数(23.2)
%Uint32Array% "Uint32Array" Uint32Array 构造函数(23.2)
%URIError% "URIError" URIError 构造函数(20.5.5.6)
%WeakMap% "WeakMap" WeakMap 构造函数(24.3.1)
%WeakRef% "WeakRef" WeakRef 构造函数(26.1.1)
%WeakSet% "WeakSet" WeakSet 构造函数(24.4.1)
%WrapForValidIteratorPrototype% Iterator.from 返回的包装迭代器对象的原型(27.1.3.2.2.1)
注

其他条目见 表 103。

6.2 ECMAScript 规范类型

规范类型对应于算法中用于描述 ECMAScript 语言构造和 ECMAScript 语言类型语义的元值。规范类型包括 Reference Record、List、Completion Record、Property Descriptor、Environment Record、Abstract Closure 和 Data Block。规范类型值是规范产物,不一定对应于 ECMAScript 实现中的任何特定实体。规范类型值可用于描述 ECMAScript 表达式求值的中间结果,但此类值不能存储为对象的属性或 ECMAScript 语言变量的值。

6.2.1 Enum 规范类型

Enum 是规范内部使用且无法从 ECMAScript 代码中直接观察到的值。Enum 使用 sans-serif 字体以大写 kebab case 表示。例如,Completion Record 的 [[Type]] 字段可以取 normal、return 或 throw 等值。Enum 除名称之外没有其他特征。Enum 的名称除了将其与其他 Enum 区分开之外没有其他用途,也不暗示其在上下文中的用途或含义。

6.2.2 List 和 Record 规范类型

List 类型用于说明 new 表达式、函数调用以及其他需要简单有序值列表的算法中参数列表(参见 13.3.8)的求值。List 类型的值只是由各个值组成的列表元素的有序序列。这些序列可以具有任意长度。可以使用从 0 开始的索引随机访问列表元素。为了便于表示,可以使用类似数组的语法访问 List 元素。例如,args[2] 是“List args 的第 3个元素”的简写。

当算法在未指定顺序的情况下迭代 List 的元素时,所使用的顺序就是这些元素在 List 中的顺序。

为了便于本规范中的表示,可以使用字面量语法来表示新的 List 值。例如,« 1, 2 » 定义了一个具有两个元素的 List 值,其中每个元素都初始化为特定值。新的空 List 可以表示为 « »。

在本规范中,短语“A、B、... 的列表连接”(其中每个参数都是可能为空的 List)表示一个新的 List 值,其元素是按照各参数的顺序,将每个参数中的元素依次连接而成的。

应用于 String 的 List 时,短语“按照码元字典序排序”表示:按照每个码元的数值进行排序,比较到较短字符串的长度为止;如果所有码元均相等,则将较短字符串排在较长字符串之前,如抽象操作 IsLessThan 中所述。

Record 类型用于描述本规范算法中的数据聚合。Record 类型值由一个或多个具名字段组成。每个字段的值都是 ECMAScript 语言值或规范值。字段名称始终括在双重方括号中,例如 [[Value]]。

为了便于本规范中的表示,可以使用类似对象字面量的语法来表示 Record。例如,{ [[Field1]]: 42, [[Field2]]: false, [[Field3]]: empty } 定义了一个具有三个字段的 Record,每个字段都初始化为特定值。字段名称的顺序无关紧要。任何未显式列出的字段都被视为不存在。

在规范文本和算法中,可以使用点表示法引用 Record 的特定字段。例如,如果 R 是上一段所示的 Record,则 R.[[Field2]] 是“R 中名为 [[Field2]] 的字段”的简写。

常用 Record 字段组合的模式可以命名,并且该名称可作为字面量 Record 的前缀,用于标识所描述的具体聚合种类。例如:PropertyDescriptor { [[Value]]: 42, [[Writable]]: false, [[Configurable]]: true }。

6.2.3 Set 和 Relation 规范类型

Set 类型用于说明内存模型中使用的无序元素集合。它不同于同名的 ECMAScript 集合类型。为消除歧义,本规范始终将 ECMAScript 集合的实例称为“Set 对象”。Set 类型的值是元素的简单集合,其中任何元素都不会出现多次。可以向 Set 中添加元素,也可以从 Set 中移除元素。Set 之间可以进行并集、交集或差集运算。

Relation 类型用于说明对 Set 的约束。Relation 类型的值是由其值域中的值的有序对组成的 Set。例如,Memory 事件上的 Relation 是由 Memory 事件的有序对组成的集合。对于 Relation R 以及 R 值域中的两个值 a 和 b,a R b 是“有序对 (a, b) 是 R 的成员”的简写。当一个 Relation 是满足某些条件的最小 Relation 时,它是关于这些条件的最小 Relation。

严格偏序是满足以下条件的 Relation 值 R。

  • 对于 R 的定义域中的所有 a、b 和 c:

    • 不存在 a R a,并且
    • 如果 a R b 且 b R c,则 a R c。
注 1

上述两个性质分别称为非自反性和传递性。

严格全序是满足以下条件的 Relation 值 R。

  • 对于 R 的定义域中的所有 a、b 和 c:

    • a 是 b,或者 a R b,或者 b R a,并且
    • 不存在 a R a,并且
    • 如果 a R b 且 b R c,则 a R c。
注 2

上述三个性质分别称为完全性、非自反性和传递性。

6.2.4 Completion Record 规范类型

Completion Record 规范类型用于说明值和控制流在运行时的传播,例如执行非局部控制转移的语句(break、continue、return 和 throw)的行为。

Completion Record 具有 表 7 中定义的字段。

表 7: Completion Record 字段
字段名称 值 含义
[[Type]] normal、break、continue、return 或 throw 发生的完成类型。
[[Value]] 除 Completion Record 之外的任意值 所产生的值。
[[Target]] String 或 empty 定向控制转移的目标标签。

有时使用以下简写术语来指代 Completion Record。

  • 正常完成指 [[Type]] 值为 normal 的任何 Completion Record。
  • break 完成指 [[Type]] 值为 break 的任何 Completion Record。
  • continue 完成指 [[Type]] 值为 continue 的任何 Completion Record。
  • return 完成指 [[Type]] 值为 return 的任何 Completion Record。
  • throw 完成指 [[Type]] 值为 throw 的任何 Completion Record。
  • 突然完成指 [[Type]] 值不是 normal 的任何 Completion Record。
  • 包含某种类型值的正常完成,指其 [[Value]] 字段中具有该类型值的正常完成。

本规范中定义的可调用对象只返回正常完成或抛出完成。返回任何其他类型的 Completion Record 都被视为编辑错误。

实现定义的可调用对象必须返回正常完成或抛出完成。

6.2.4.1 NormalCompletion ( value )

抽象操作 NormalCompletion,接收参数 value (any value except a Completion 记录);返回值:正常完成。 调用时执行以下步骤:

  1. 返回 Completion Record { [[Type]]: normal, [[Value]]: value, [[Target]]: empty }。

6.2.4.2 ThrowCompletion ( value )

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

  1. 返回 Completion Record { [[Type]]: throw, [[Value]]: value, [[Target]]: empty }。

6.2.4.3 ReturnCompletion ( value )

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

  1. 返回 Completion Record { [[Type]]: return, [[Value]]: value, [[Target]]: empty }。

6.2.4.4 UpdateEmpty ( completionRecord, value )

抽象操作 UpdateEmpty,接收参数 completionRecord (完成记录) 和 value (any value except a Completion 记录);返回值:完成记录。 调用时执行以下步骤:

  1. 断言:如果 completionRecord 是 return 完成或 throw 完成,则 completionRecord.[[Value]] 不是 empty。
  2. 如果 completionRecord.[[Value]] 不是 empty,则返回 ? completionRecord。
  3. 返回 Completion Record { [[Type]]: completionRecord.[[Type]], [[Value]]: value, [[Target]]: completionRecord.[[Target]] }。

6.2.5 Reference Record 规范类型

Reference Record 类型用于说明 delete、typeof、赋值运算符、super 关键字以及其他语言特性等的行为。例如,赋值的左操作数应产生一个 Reference Record。

Reference Record 是已解析的名称或(可能尚未解析的)属性绑定;其字段由 表 8 定义。

表 8: Reference Record 字段
字段名称 值 含义
[[Base]] ECMAScript 语言值、Environment Record 或 unresolvable 持有该绑定的值或 Environment Record。[[Base]] 为 unresolvable 表示无法解析该绑定。
[[ReferencedName]] ECMAScript 语言值或 Private Name 绑定的名称。如果 [[Base]] 值是 Environment Record,则始终为 String。否则,在执行 ToPropertyKey 之前,可以是 String 或 Symbol 以外的 ECMAScript 语言值。
[[Strict]] Boolean 如果 Reference Record 源自严格模式代码,则为 true,否则为 false。
[[ThisValue]] ECMAScript 语言值或 empty 如果不是 empty,则 Reference Record 表示使用 super 关键字表达的属性绑定;它称为 Super Reference Record,并且其 [[Base]] 值永远不会是 Environment Record。在这种情况下,[[ThisValue]] 字段保存创建 Reference Record 时的 this 值。

本规范使用以下抽象操作来操作 Reference Record:

6.2.5.1 IsPropertyReference ( refRecord )

抽象操作 IsPropertyReference,接收参数 refRecord (Reference 记录);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 refRecord.[[Base]] 是 unresolvable,则返回 false。
  2. 如果 refRecord.[[Base]] 是 Environment Record,则返回 false。
  3. 返回 true。

6.2.5.2 IsUnresolvableReference ( refRecord )

抽象操作 IsUnresolvableReference,接收参数 refRecord (Reference 记录);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 refRecord.[[Base]] 是 unresolvable,则返回 true。
  2. 返回 false。

6.2.5.3 IsSuperReference ( refRecord )

抽象操作 IsSuperReference,接收参数 refRecord (Reference 记录);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 refRecord.[[ThisValue]] 是 empty,则返回 false。
  2. 返回 true。

6.2.5.4 IsPrivateReference ( refRecord )

抽象操作 IsPrivateReference,接收参数 refRecord (Reference 记录);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 refRecord.[[ReferencedName]] 是 Private Name,则返回 true。
  2. 返回 false。

6.2.5.5 GetValue ( refRecord )

抽象操作 GetValue,接收参数 refRecord ((Reference 记录 或 ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 调用时执行以下步骤:

  1. 如果 refRecord 不是 Reference Record,则返回 refRecord。
  2. 如果 IsUnresolvableReference(refRecord) 是 true,则抛出 ReferenceError 异常。
  3. 如果 IsPropertyReference(refRecord) 是 true,则
    1. 令 baseObj 为 ? ToObject(refRecord.[[Base]])。
    2. 如果 IsPrivateReference(refRecord) 是 true,则
      1. 返回 ? PrivateGet(baseObj, refRecord.[[ReferencedName]])。
    3. 如果 refRecord.[[ReferencedName]] 不是属性键,则
      1. 将 refRecord.[[ReferencedName]] 设置为 ? ToPropertyKey(refRecord.[[ReferencedName]])。
    4. 返回 ? baseObj.[[Get]](refRecord.[[ReferencedName]], GetThisValue(refRecord))。
  4. 令 base 为 refRecord.[[Base]]。
  5. 断言:base 是 Environment Record。
  6. 返回 ? base.GetBindingValue(refRecord.[[ReferencedName]], refRecord.[[Strict]])(参见 9.1)。
注

步骤 3.a 中可能创建的对象无法在上述抽象操作和普通对象 [[Get]] 内部方法之外访问。实现可以选择避免实际创建该对象。

6.2.5.6 PutValue ( refRecord, value )

抽象操作 PutValue,接收参数 refRecord ((Reference 记录 或 ECMAScript 语言值)) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 突兀完成)。 调用时执行以下步骤:

  1. 如果 refRecord 不是 Reference Record,则抛出 ReferenceError 异常。
  2. 如果 IsUnresolvableReference(refRecord) 是 true,则
    1. 如果 refRecord.[[Strict]] 是 true,则抛出 ReferenceError 异常。
    2. 令 globalObj 为 GetGlobalObject()。
    3. 执行 ? Set(globalObj, refRecord.[[ReferencedName]], value, false)。
    4. 返回 unused。
  3. 如果 IsPropertyReference(refRecord) 是 true,则
    1. 令 baseObj 为 ? ToObject(refRecord.[[Base]])。
    2. 如果 IsPrivateReference(refRecord) 是 true,则
      1. 返回 ? PrivateSet(baseObj, refRecord.[[ReferencedName]], value)。
    3. 如果 refRecord.[[ReferencedName]] 不是属性键,则
      1. 将 refRecord.[[ReferencedName]] 设置为 ? ToPropertyKey(refRecord.[[ReferencedName]])。
    4. 令 succeeded 为 ? baseObj.[[Set]](refRecord.[[ReferencedName]], value, GetThisValue(refRecord))。
    5. 如果 succeeded 是 false 且 refRecord.[[Strict]] 是 true,则抛出 TypeError 异常。
    6. 返回 unused。
  4. 令 base 为 refRecord.[[Base]]。
  5. 断言:base 是 Environment Record。
  6. 返回 ? base.SetMutableBinding(refRecord.[[ReferencedName]], value, refRecord.[[Strict]])(参见 9.1)。
注

步骤 3.a 中可能创建的对象无法在上述抽象操作和普通对象 [[Set]] 内部方法之外访问。实现可以选择避免实际创建该对象。

6.2.5.7 GetThisValue ( refRecord )

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

  1. 断言:IsPropertyReference(refRecord) 是 true。
  2. 如果 IsSuperReference(refRecord) 是 true,则返回 refRecord.[[ThisValue]]。
  3. 返回 refRecord.[[Base]]。

6.2.5.8 InitializeReferencedBinding ( refRecord, value )

抽象操作 InitializeReferencedBinding,接收参数 refRecord (Reference 记录) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 突兀完成)。 调用时执行以下步骤:

  1. 断言:IsUnresolvableReference(refRecord) 是 false。
  2. 令 base 为 refRecord.[[Base]]。
  3. 断言:base 是 Environment Record。
  4. 返回 ? base.InitializeBinding(refRecord.[[ReferencedName]], value)。

6.2.5.9 MakePrivateReference ( baseValue, privateIdentifier )

抽象操作 MakePrivateReference,接收参数 baseValue (ECMAScript 语言值) 和 privateIdentifier (String);返回值:Reference 记录。 调用时执行以下步骤:

  1. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  2. 断言:privateEnv 不是 null。
  3. 令 privateName 为 ResolvePrivateIdentifier(privateEnv, privateIdentifier)。
  4. 返回 Reference Record { [[Base]]: baseValue, [[ReferencedName]]: privateName, [[Strict]]: true, [[ThisValue]]: empty }。

6.2.6 Property Descriptor 规范类型

Property Descriptor 类型用于说明 Object 属性特性的操作和具体化。Property Descriptor 是具有零个或多个字段的 Record,其中每个字段的名称都是特性名称,其值是 6.1.7.1 中规定的相应特性值。本规范中用于标记 Property Descriptor Record 字面量描述的模式名称是“PropertyDescriptor”。

根据某些字段是否存在或被使用,Property Descriptor 值还可以进一步分类为数据 Property Descriptor 和访问器 Property Descriptor。数据 Property Descriptor 是包含名为 [[Value]] 或 [[Writable]] 的任意字段的 Property Descriptor。访问器 Property Descriptor 是包含名为 [[Getter]] 或 [[Setter]] 的任意字段的 Property Descriptor。任何 Property Descriptor 都可以具有名为 [[Enumerable]] 和 [[Configurable]] 的字段。Property Descriptor 值不能同时是数据 Property Descriptor 和访问器 Property Descriptor;不过,它也可以两者都不是(在这种情况下,它是通用 Property Descriptor)。完全填充的 Property Descriptor是访问器 Property Descriptor 或数据 Property Descriptor,并且具有 表 3 中定义的所有相应字段。

本规范使用以下抽象操作来操作 Property Descriptor 值:

6.2.6.1 IsAccessorDescriptor ( propertyDesc )

抽象操作 IsAccessorDescriptor,接收参数 propertyDesc (属性描述符);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 propertyDesc 具有 [[Getter]] 字段,则返回 true。
  2. 如果 propertyDesc 具有 [[Setter]] 字段,则返回 true。
  3. 返回 false。

6.2.6.2 IsDataDescriptor ( propertyDesc )

抽象操作 IsDataDescriptor,接收参数 propertyDesc (属性描述符);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 propertyDesc 具有 [[Value]] 字段,则返回 true。
  2. 如果 propertyDesc 具有 [[Writable]] 字段,则返回 true。
  3. 返回 false。

6.2.6.3 IsGenericDescriptor ( propertyDesc )

抽象操作 IsGenericDescriptor,接收参数 propertyDesc (属性描述符);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 IsAccessorDescriptor(propertyDesc) 是 true,则返回 false。
  2. 如果 IsDataDescriptor(propertyDesc) 是 true,则返回 false。
  3. 返回 true。

6.2.6.4 FromPropertyDescriptor ( propertyDesc )

抽象操作 FromPropertyDescriptor,接收参数 propertyDesc ((属性描述符 或 undefined));返回值:(Object 或 undefined)。 调用时执行以下步骤:

  1. 如果 propertyDesc 是 undefined,则返回 undefined。
  2. 令 obj 为 OrdinaryObjectCreate(%Object.prototype%)。
  3. 断言:obj 是没有自有属性的可扩展普通对象。
  4. 如果 propertyDesc 具有 [[Value]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "value", propertyDesc.[[Value]])。
  5. 如果 propertyDesc 具有 [[Writable]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "writable", propertyDesc.[[Writable]])。
  6. 如果 propertyDesc 具有 [[Getter]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "get", propertyDesc.[[Getter]])。
  7. 如果 propertyDesc 具有 [[Setter]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "set", propertyDesc.[[Setter]])。
  8. 如果 propertyDesc 具有 [[Enumerable]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "enumerable", propertyDesc.[[Enumerable]])。
  9. 如果 propertyDesc 具有 [[Configurable]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "configurable", propertyDesc.[[Configurable]])。
  10. 返回 obj。

6.2.6.5 ToPropertyDescriptor ( obj )

抽象操作 ToPropertyDescriptor,接收参数 obj (ECMAScript 语言值);返回值:(正常完成 (值:属性描述符) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 obj 不是 Object,则抛出 TypeError 异常。
  2. 令 propertyDesc 为一个最初不具有任何字段的新 Property Descriptor。
  3. 令 hasEnumerable 为 ? HasProperty(obj, "enumerable")。
  4. 如果 hasEnumerable 是 true,则
    1. 令 enumerable 为 ToBoolean(? Get(obj, "enumerable")).
    2. 将 propertyDesc.[[Enumerable]] 设置为 enumerable。
  5. 令 hasConfigurable 为 ? HasProperty(obj, "configurable")。
  6. 如果 hasConfigurable 是 true,则
    1. 令 configurable 为 ToBoolean(? Get(obj, "configurable")).
    2. 将 propertyDesc.[[Configurable]] 设置为 configurable。
  7. 令 hasValue 为 ? HasProperty(obj, "value")。
  8. 如果 hasValue 是 true,则
    1. 令 value 为 ? Get(obj, "value")。
    2. 将 propertyDesc.[[Value]] 设置为 value。
  9. 令 hasWritable 为 ? HasProperty(obj, "writable")。
  10. 如果 hasWritable 是 true,则
    1. 令 writable 为 ToBoolean(? Get(obj, "writable")).
    2. 将 propertyDesc.[[Writable]] 设置为 writable。
  11. 令 hasGet 为 ? HasProperty(obj, "get")。
  12. 如果 hasGet 是 true,则
    1. 令 getter 为 ? Get(obj, "get")。
    2. 如果 IsCallable(getter) 是 false 且 getter 不是 undefined,则抛出 TypeError 异常。
    3. 将 propertyDesc.[[Getter]] 设置为 getter。
  13. 令 hasSet 为 ? HasProperty(obj, "set")。
  14. 如果 hasSet 是 true,则
    1. 令 setter 为 ? Get(obj, "set")。
    2. 如果 IsCallable(setter) 是 false 且 setter 不是 undefined,则抛出 TypeError 异常。
    3. 将 propertyDesc.[[Setter]] 设置为 setter。
  15. 如果 propertyDesc 具有 [[Getter]] 字段或 propertyDesc 具有 [[Setter]] 字段,则
    1. 如果 propertyDesc 具有 [[Value]] 字段或 propertyDesc 具有 [[Writable]] 字段,则抛出 TypeError 异常。
  16. 返回 propertyDesc。

6.2.6.6 CompletePropertyDescriptor ( propertyDesc )

抽象操作 CompletePropertyDescriptor,接收参数 propertyDesc (属性描述符);返回值:unused。 调用时执行以下步骤:

  1. 令 like 为 Record { [[Value]]: undefined, [[Writable]]: false, [[Getter]]: undefined, [[Setter]]: undefined, [[Enumerable]]: false, [[Configurable]]: false }。
  2. 如果 IsGenericDescriptor(propertyDesc) 是 true 或 IsDataDescriptor(propertyDesc) 是 true,则
    1. 如果 propertyDesc 没有 [[Value]] 字段,则将 propertyDesc.[[Value]] 设置为 like.[[Value]]。
    2. 如果 propertyDesc 没有 [[Writable]] 字段,则将 propertyDesc.[[Writable]] 设置为 like.[[Writable]]。
  3. 否则,
    1. 如果 propertyDesc 没有 [[Getter]] 字段,则将 propertyDesc.[[Getter]] 设置为 like.[[Getter]]。
    2. 如果 propertyDesc 没有 [[Setter]] 字段,则将 propertyDesc.[[Setter]] 设置为 like.[[Setter]]。
  4. 如果 propertyDesc 没有 [[Enumerable]] 字段,则将 propertyDesc.[[Enumerable]] 设置为 like.[[Enumerable]]。
  5. 如果 propertyDesc 没有 [[Configurable]] 字段,则将 propertyDesc.[[Configurable]] 设置为 like.[[Configurable]]。
  6. 返回 unused。

6.2.7 Environment Record 规范类型

Environment Record 类型用于说明嵌套函数和块中的名称解析行为。该类型及其操作定义于 9.1。

6.2.8 Abstract Closure 规范类型

Abstract Closure 规范类型用于引用算法步骤以及一组值。Abstract Closure 是元值,并使用函数应用形式调用,例如 closure(arg1, arg2)。与抽象操作一样,调用会执行 Abstract Closure 所描述的算法步骤。

在创建 Abstract Closure 的算法步骤中,使用动词“捕获”后跟别名列表来捕获值。创建 Abstract Closure 时,它会捕获当时与每个别名关联的值。在规定调用 Abstract Closure 时所执行算法的步骤中,每个捕获值都使用捕获该值时所用的别名引用。

如果 Abstract Closure 返回 Completion Record,则该 Completion Record 必须是正常完成或抛出完成。

Abstract Closure 作为其他算法的一部分内联创建,如以下示例所示。

  1. 令 addend 为 41。
  2. 令 closure 为一个新的 Abstract Closure,它具有参数 (x),捕获 addend,并在被调用时执行以下步骤:
    1. 返回 x + addend。
  3. 令 value 为 closure(1)。
  4. 断言:value 是 42。

6.2.9 数据块

Data Block 规范类型用于描述由字节大小(8 位)的数值组成的独立且可变序列。字节值是从 0 到 255 的闭区间中的整数。创建 Data Block 值时会指定固定数量的字节,每个字节的初始值均为 0。

为了便于本规范中的表示,可以使用类似数组的语法访问 Data Block 值的各个字节。此表示法将 Data Block 值表示为从 0 开始的整数索引字节序列。例如,如果 dataBlock 是一个 5 字节的 Data Block 值,则可以使用 dataBlock[2] 访问其第 3个字节。

位于可由多个代理同时引用的内存中的数据块称为 Shared Data Block。Shared Data Block 具有一个与地址无关的标识(用于 Shared Data Block 值的相等性测试):它不绑定到该块在任何进程中映射到的虚拟地址,而是绑定到该块所表示的内存位置集合。两个数据块仅当其包含的位置集合相等时才相等;否则它们不相等,并且其包含的位置集合的交集为空。最后,可以将 Shared Data Block 与 Data Block 区分开来。

Shared Data Block 的语义由内存模型使用 Shared Data Block 事件定义。下面的抽象操作引入 Shared Data Block 事件,并充当求值语义与内存模型事件语义之间的接口。这些事件构成一个候选执行,内存模型在其上充当过滤器。完整语义请参阅内存模型。

Shared Data Block 事件由内存模型中定义的 Record 建模。

本规范使用以下抽象操作来操作 Data Block 值:

6.2.9.1 CreateByteDataBlock ( size )

抽象操作 CreateByteDataBlock,接收参数 size (非负整数);返回值:(正常完成 (值:数据块) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 size > 253 - 1,则抛出 RangeError 异常。
  2. 令 dataBlock 为一个由 size 个字节组成的新 Data Block 值。如果无法创建这样的 Data Block,则抛出 RangeError 异常。
  3. 将 dataBlock 的所有字节设置为 0。
  4. 返回 dataBlock。

6.2.9.2 CreateSharedByteDataBlock ( size )

抽象操作 CreateSharedByteDataBlock,接收参数 size (非负整数);返回值:(正常完成 (值:共享数据块) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 dataBlock 为一个由 size 个字节组成的新 Shared Data Block 值。如果无法创建这样的 Shared Data Block,则抛出 RangeError 异常。
  2. 令 agentRecord 为周围代理的 Agent Record。
  3. 令 execution 为 agentRecord.[[CandidateExecution]]。
  4. 令 eventsRecord 为 execution.[[EventsRecords]] 中 [[AgentSignifier]] 为 AgentSignifier() 的 Agent Events Record。
  5. 令 zero 为 « 0 »。
  6. 对 dataBlock 的每个索引 index,执行
    1. 将 WriteSharedMemory { [[Order]]: init, [[NoTear]]: true, [[Block]]: dataBlock, [[ByteIndex]]: index, [[ElementSize]]: 1, [[Payload]]: zero } 追加到 eventsRecord.[[EventList]]。
  7. 返回 dataBlock。

6.2.9.3 CopyDataBlockBytes ( toBlock, toIndex, fromBlock, fromIndex, count )

抽象操作 CopyDataBlockBytes,接收参数 toBlock ((数据块 或 共享数据块))、toIndex (非负整数)、fromBlock ((数据块 或 共享数据块))、fromIndex (非负整数) 和 count (非负整数);返回值:unused。 调用时执行以下步骤:

  1. 断言:fromBlock 和 toBlock 是不同的值。
  2. 令 fromSize 为 fromBlock 中的字节数。
  3. 断言:fromIndex + count ≤ fromSize。
  4. 令 toSize 为 toBlock 中的字节数。
  5. 断言:toIndex + count ≤ toSize。
  6. 当 count > 0 时,重复执行
    1. 如果 fromBlock 是 Shared Data Block,则
      1. 令 agentRecord 为周围代理的 Agent Record。
      2. 令 execution 为 agentRecord.[[CandidateExecution]]。
      3. 令 eventsRecord 为 execution.[[EventsRecords]] 中 [[AgentSignifier]] 为 AgentSignifier() 的 Agent Events Record。
      4. 令 bytes 为一个 List,其唯一元素是非确定性选择的字节值。
      5. 注:在实现中,bytes 是底层硬件上的非原子读取指令的结果。这种非确定性是内存模型的语义规定,用于描述弱一致性硬件的可观察行为。
      6. 令 readEvent 为 ReadSharedMemory { [[Order]]: unordered, [[NoTear]]: true, [[Block]]: fromBlock, [[ByteIndex]]: fromIndex, [[ElementSize]]: 1 }。
      7. 将 readEvent 追加到 eventsRecord.[[EventList]]。
      8. 将 Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: bytes } 追加到 execution.[[ChosenValues]]。
      9. 如果 toBlock 是 Shared Data Block,则
        1. 将 WriteSharedMemory { [[Order]]: unordered, [[NoTear]]: true, [[Block]]: toBlock, [[ByteIndex]]: toIndex, [[ElementSize]]: 1, [[Payload]]: bytes } 追加到 eventsRecord.[[EventList]]。
      10. 否则,
        1. 将 toBlock[toIndex] 设置为 bytes[0]。
    2. 否则,
      1. 断言:toBlock 不是 Shared Data Block。
      2. 将 toBlock[toIndex] 设置为 fromBlock[fromIndex]。
    3. 将 toIndex 设置为 toIndex + 1。
    4. 将 fromIndex 设置为 fromIndex + 1。
    5. 将 count 设置为 count - 1。
  7. 返回 unused。

6.2.10 PrivateElement 规范类型

PrivateElement 类型是一种 Record,用于规范私有类字段、方法和访问器。尽管私有元素不与 Property Descriptor 关联,也不是属性,但引用它们的表达式的运行时语义在某些方面与不可配置属性的运行时语义相似(私有字段类似于可写数据属性,私有方法类似于不可写数据属性,私有访问器类似于访问器属性),相应的 Record 字段也用于类似的目的。

PrivateElement 类型的值是其字段由 表 9 定义的 Record。此类值称为 PrivateElement 记录。

表 9: PrivateElement 字段
字段名称 存在该字段的 [[Kind]] 字段值 值 含义
[[Key]] 全部 Private Name 字段、方法或访问器的名称。
[[Kind]] 全部 field、method 或 accessor 元素的种类。
[[Value]] field 和 method ECMAScript 语言值 字段的值。
[[Getter]] accessor 函数对象或 undefined 私有访问器的 getter。
[[Setter]] accessor 函数对象或 undefined 私有访问器的 setter。

6.2.11 ClassFieldDefinition Record 规范类型

ClassFieldDefinition 类型是用于规定类字段的 Record。

ClassFieldDefinition 类型的值是其字段由 表 10 定义的 Record。此类值称为 ClassFieldDefinition 记录。

表 10: ClassFieldDefinition Record 字段
字段名称 值 含义
[[Name]] Private Name、String 或 Symbol 字段的名称。
[[Initializer]] ECMAScript 函数对象或 empty 字段的初始化器(如果有)。

6.2.12 Private Name

Private Name 规范类型用于描述全局唯一的值(即使两个 Private Name 在其他方面无法区分,它们也彼此不同),该值表示私有类元素(字段、方法或访问器)的键。每个 Private Name 都有一个不可变的 [[Description]] 内部槽,其值为 String。可以使用 PrivateFieldAdd 或 PrivateMethodOrAccessorAdd 将 Private Name 安装到任何 ECMAScript 对象上,然后使用 PrivateGet 和 PrivateSet 读取或写入。

6.2.13 ClassStaticBlockDefinition Record 规范类型

ClassStaticBlockDefinition Record 是用于封装类静态初始化块可执行代码的 Record。

ClassStaticBlockDefinition Record 具有 表 11 中列出的字段。

表 11: ClassStaticBlockDefinition Record 字段
字段名称 值 含义
[[BodyFunction]] ECMAScript 函数对象 在类的静态初始化期间调用的函数对象。