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 类型表示具有两个值的逻辑实体,这两个值称为 truefalse

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 值,但其他操作不会隐式规范化它们所操作的字符串。除非另有说明,操作结果不受语言和/或区域设置影响。

Note

此设计背后的理由是,使 Strings 的实现尽可能简单且高性能。如果 ECMAScript 源文本采用 Normalized Form C,则只要字符串字面量不包含任何 Unicode 转义序列,就保证它们也被规范化。

在本规范中,短语“AB、... 的字符串连接”(其中每个实参都是 String 值、码元或码元序列)表示一个 String 值,其码元序列是每个实参的码元(按顺序)的连接(按顺序)。

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

短语“ASCII 单词字符”表示以下 String 值,该值仅由 Unicode Basic Latin 块中的每个字母和数字以及 U+005F(LOW LINE)组成:
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"
出于历史原因,它对各种算法具有意义。

6.1.4.1 StringIndexOf ( string, searchValue, fromIndex )

The abstract operation StringIndexOf takes arguments string (a String), searchValue (a String), and fromIndex (a non-negative integer) and returns a non-negative integer or not-found. It performs the following steps when called:

  1. lengthstring 的长度。
  2. 如果 searchValue 为空 String 且 fromIndexlength,则返回 fromIndex
  3. searchLengthsearchValue 的长度。
  4. 对于满足 fromIndexilength - searchLength 的每个整数 i,按升序执行:
    1. candidatestringii + searchLength子字符串
    2. 如果 candidatesearchValue,则返回 i
  5. 返回 not-found
Note 1

如果 searchValue 为空 String 且 fromIndexstring 的长度,则该算法返回 fromIndex。空 String 实际上会在字符串内的每个位置被找到,包括最后一个码元之后。

Note 2

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

6.1.4.2 StringLastIndexOf ( string, searchValue, fromIndex )

The abstract operation StringLastIndexOf takes arguments string (a String), searchValue (a String), and fromIndex (a non-negative integer) and returns a non-negative integer or not-found. It performs the following steps when called:

  1. lengthstring 的长度。
  2. searchLengthsearchValue 的长度。
  3. 断言:fromIndex + searchLengthlength
  4. 对于满足 0 ≤ ifromIndex 的每个整数 i,按降序执行:
    1. candidatestringii + searchLength子字符串
    2. 如果 candidatesearchValue,则返回 i
  5. 返回 not-found
Note

如果 searchValue 为空 String,则该算法返回 fromIndex。空 String 实际上会在字符串内的每个位置被找到,包括最后一个码元之后。

6.1.5 Symbol 类型

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

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

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

6.1.5.1 众所周知的 Symbols

众所周知的 symbols 是由本规范的算法显式引用的内置 Symbol 值。它们通常用作属性的键,而这些属性的值充当规范算法的扩展点。除非另有规定,众所周知的 symbol 值由所有 realms 共享(9.3)。

在本规范中,使用标准内在记号引用众所周知的 symbol,其中该内在是 Table 1 中列出的值之一。

Note
本规范的早期版本使用形如 @@name 的记号,而当前版本会使用 %Symbol.name%。特别地,曾使用以下名称:@@asyncIterator、@@hasInstance、@@isConcatSpreadable、@@iterator、@@match、@@matchAll、@@replace、@@search、@@species、@@split、@@toPrimitive、@@toStringTag 和 @@unscopables。
Table 1: 众所周知的 Symbol
规范名称 [[描述]] 值和用途
%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" 一个 function 值属性,它是用于创建派生对象的构造函数
%Symbol.split% "Symbol.split" 一个正则表达式方法,用于在与正则表达式匹配的索引处拆分字符串。由 String.prototype.split 方法调用。
%Symbol.toPrimitive% "Symbol.toPrimitive" 一个方法,用于将对象转换为对应的原始值。由 ToPrimitive 抽象操作调用。
%Symbol.toStringTag% "Symbol.toStringTag" 一个 String 值属性,用于创建对象的默认字符串描述。由内置方法 Object.prototype.toString 访问。
%Symbol.unscopables% "Symbol.unscopables" 一个 object 值属性,其自身和继承的属性名,是要从关联对象的 with 环境绑定中排除的属性名

6.1.6 数值类型

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

Table 2: Numeric Type Operations
操作 示例源代码 由……的 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) 对象内部方法, 经由 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 语言不在这些类型之间提供隐式转换。调用需要另一种类型的函数时,程序员必须显式调用 NumberBigInt 函数以在类型之间转换。

Note

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

6.1.6.1 Number 类型

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

Note

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

还有另外两个特殊值,称为 positive Infinitynegative Infinity。为简洁起见,出于说明目的,这些值也分别用符号 +∞𝔽-∞𝔽 指代。(注意,这两个无穷 Number 值由程序表达式 +Infinity(或简单地 Infinity)和 -Infinity 产生。)

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

注意,存在 positive zeronegative zero。为简洁起见,出于说明目的,这些值也分别用符号 +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𝔽

如果有限数非零,且用于以上两种形式之一表示它的整数 m 为奇数,则它具有奇数有效数。否则,它具有偶数有效数

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

+∞ 的 Number 值+∞𝔽,-∞ 的 Number 值-∞𝔽

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

6.1.6.1.1 Number::unaryMinus ( number )

The abstract operation Number::unaryMinus takes argument number (a Number) and returns a Number. It performs the following steps when called:

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

6.1.6.1.2 Number::bitwiseNOT ( number )

The abstract operation Number::bitwiseNOT takes argument number (a Number) and returns an integral Number. It performs the following steps when called:

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

6.1.6.1.3 Number::exponentiate ( base, exponent )

The abstract operation Number::exponentiate takes arguments base (a Number) and exponent (a Number) and returns a Number. 它返回一个实现近似值,表示 baseexponent 次幂结果。 It performs the following steps when called:

  1. 如果 exponentNaN,则返回 NaN
  2. 如果 exponent+0𝔽-0𝔽,则返回 1𝔽
  3. 如果 baseNaN,则返回 NaN
  4. 如果 base+∞𝔽,则
    1. 如果 exponent > +0𝔽,则返回 +∞𝔽
    2. 返回 +0𝔽
  5. 如果 base-∞𝔽,则
    1. 如果 exponent > +0𝔽,则
      1. 如果 exponent 是奇数 integral Number,则返回 -∞𝔽
      2. 返回 +∞𝔽
    2. 如果 exponent 是奇数 integral Number,则返回 -0𝔽
    3. 返回 +0𝔽
  6. 如果 base+0𝔽,则
    1. 如果 exponent > +0𝔽,则返回 +0𝔽
    2. 返回 +∞𝔽
  7. 如果 base-0𝔽,则
    1. 如果 exponent > +0𝔽,则
      1. 如果 exponent 是奇数 integral Number,则返回 -0𝔽
      2. 返回 +0𝔽
    2. 如果 exponent 是奇数 integral Number,则返回 -∞𝔽
    3. 返回 +∞𝔽
  8. 断言:base有限的,且既不是 +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有限的,且既不是 +0𝔽 也不是 -0𝔽
  12. 如果 base < -0𝔽exponent 不是 integral Number,则返回 NaN
  13. 返回一个实现近似的 Number 值,表示将 (base) 提升到 (exponent) 次幂的结果。
Note

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

6.1.6.1.4 Number::multiply ( x, y )

The abstract operation Number::multiply takes arguments x (a Number) and y (a Number) and returns a Number. 它按照 IEEE 754-2019 二进制双精度算术规则执行乘法,产生 xy 的乘积。 It performs the following steps when called:

  1. 如果 xNaNyNaN,则返回 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))。
Note

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

6.1.6.1.5 Number::divide ( x, y )

The abstract operation Number::divide takes arguments x (a Number) and y (a Number) and returns a Number. 它按照 IEEE 754-2019 二进制双精度算术规则执行除法,产生 xy 的商,其中 x 是被除数,y 是除数。 It performs the following steps when called:

  1. 如果 xNaNyNaN,则返回 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 )

The abstract operation Number::remainder takes arguments numerator (a Number) and denominator (a Number) and returns a Number. 它产生由其操作数的隐含除法得到的余数,其中 numerator 是被除数,denominator 是除数。 It performs the following steps when called:

  1. 如果 numeratorNaNdenominatorNaN,则返回 NaN
  2. 如果 numerator+∞𝔽-∞𝔽,则返回 NaN
  3. 如果 denominator+∞𝔽-∞𝔽,则返回 numerator
  4. 如果 denominator+0𝔽-0𝔽,则返回 NaN
  5. 如果 numerator+0𝔽-0𝔽,则返回 numerator
  6. 断言:numeratordenominator有限且非零的。
  7. quotient(numerator) / (denominator)。
  8. truncatedQuotienttruncate(quotient)。
  9. remainder(numerator) - ((denominator) × truncatedQuotient)。
  10. 如果 remainder = 0 且 numerator < -0𝔽,则返回 -0𝔽
  11. 返回 𝔽(remainder)。
Note 1

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

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

6.1.6.1.7 Number::add ( x, y )

The abstract operation Number::add takes arguments x (a Number) and y (a Number) and returns a Number. 它按照 IEEE 754-2019 二进制双精度算术规则执行加法,产生其实参之和。 It performs the following steps when called:

  1. 如果 xNaNyNaN,则返回 NaN
  2. 如果 x+∞𝔽y-∞𝔽,则返回 NaN
  3. 如果 x-∞𝔽y+∞𝔽,则返回 NaN
  4. 如果 x+∞𝔽-∞𝔽,则返回 x
  5. 如果 y+∞𝔽-∞𝔽,则返回 y
  6. 断言:xy 都是有限的。
  7. 如果 x-0𝔽y-0𝔽,则返回 -0𝔽
  8. 返回 𝔽((x) + (y))。
Note

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

6.1.6.1.8 Number::subtract ( x, y )

The abstract operation Number::subtract takes arguments x (a Number) and y (a Number) and returns a Number. 它执行减法,产生其操作数之差;x 是被减数,y 是减数。 It performs the following steps when called:

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

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

6.1.6.1.9 Number::leftShift ( x, y )

The abstract operation Number::leftShift takes arguments x (a Number) and y (a Number) and returns an integral Number. It performs the following steps when called:

  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 )

The abstract operation Number::signedRightShift takes arguments x (a Number) and y (a Number) and returns an integral Number. It performs the following steps when called:

  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 )

The abstract operation Number::unsignedRightShift takes arguments x (a Number) and y (a Number) and returns an integral Number. It performs the following steps when called:

  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 )

The abstract operation Number::lessThan takes arguments x (a Number) and y (a Number) and returns a Boolean or undefined. It performs the following steps when called:

  1. 如果 xNaN,则返回 undefined
  2. 如果 yNaN,则返回 undefined
  3. 如果 xy,则返回 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. 断言:xy有限的。
  11. 如果 (x) < (y),则返回 true
  12. 返回 false

6.1.6.1.13 Number::equal ( x, y )

The abstract operation Number::equal takes arguments x (a Number) and y (a Number) and returns a Boolean. It performs the following steps when called:

  1. 如果 xNaN,则返回 false
  2. 如果 yNaN,则返回 false
  3. 如果 xy,则返回 true
  4. 如果 x+0𝔽y-0𝔽,则返回 true
  5. 如果 x-0𝔽y+0𝔽,则返回 true
  6. 返回 false

6.1.6.1.14 Number::sameValue ( x, y )

The abstract operation Number::sameValue takes arguments x (a Number) and y (a Number) and returns a Boolean. It performs the following steps when called:

  1. 如果 xNaNyNaN,则返回 true
  2. 如果 x+0𝔽y-0𝔽,则返回 false
  3. 如果 x-0𝔽y+0𝔽,则返回 false
  4. 如果 xy,则返回 true
  5. 返回 false

6.1.6.1.15 Number::sameValueZero ( x, y )

The abstract operation Number::sameValueZero takes arguments x (a Number) and y (a Number) and returns a Boolean. It performs the following steps when called:

  1. 如果 xNaNyNaN,则返回 true
  2. 如果 x+0𝔽y-0𝔽,则返回 true
  3. 如果 x-0𝔽y+0𝔽,则返回 true
  4. 如果 xy,则返回 true
  5. 返回 false

6.1.6.1.16 NumberBitwiseOp ( op, x, y )

The abstract operation NumberBitwiseOp takes arguments op (&, ^, or |), x (a Number), and y (a Number) and returns an integral Number. It performs the following steps when called:

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

6.1.6.1.17 Number::bitwiseAND ( x, y )

The abstract operation Number::bitwiseAND takes arguments x (a Number) and y (a Number) and returns an integral Number. It performs the following steps when called:

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

6.1.6.1.18 Number::bitwiseXOR ( x, y )

The abstract operation Number::bitwiseXOR takes arguments x (a Number) and y (a Number) and returns an integral Number. It performs the following steps when called:

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

6.1.6.1.19 Number::bitwiseOR ( x, y )

The abstract operation Number::bitwiseOR takes arguments x (a Number) and y (a Number) and returns an integral Number. It performs the following steps when called:

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

6.1.6.1.20 Number::toString ( x, radix )

The abstract operation Number::toString takes arguments x (a Number) and radix (an integer in the inclusive interval from 2 to 36) and returns a String. 它使用基数为 radix 的位置计数系统,将 x 表示为 String。使用基数 r 表示数时所用的数字,按顺序取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个码元。大小大于或等于 1𝔽 的数的表示从不包含前导零。 It performs the following steps when called:

  1. 如果 xNaN,则返回 "NaN"
  2. 如果 x+0𝔽-0𝔽,则返回 "0"
  3. 如果 x < -0𝔽,则返回 "-"Number::toString(-x, radix) 的字符串连接
  4. 如果 x+∞𝔽,则返回 "Infinity"
  5. nks 为整数,使得 k ≥ 1,radixk - 1s < radixk𝔽(s × radixn - k) 是 x,并且 k 尽可能小。注意,k 是使用基数 radix 表示 s 时的位数,s 不能被 radix 整除,并且 s 的最低有效位不一定由这些条件唯一确定。
  6. 如果 radix ≠ 10 或 n 位于从 -5 到 21 的闭区间内,则
    1. 如果 nk,则
      1. 返回以下项的字符串连接
        • 使用基数 radix 表示 sk 个数字的码元
        • 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 表示 sk 个数字的码元
  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) 的十进制表示的码元
Note 1

以下观察对实现可作为指南而有用,但不是本标准规范性要求的一部分:

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

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

  1. nks 为整数,使得 k ≥ 1,radixk - 1s < radixk𝔽(s × radixn - k) 是 x,并且 k 尽可能小。如果 s 有多种可能,则选择使 s × radixn - k 最接近 (x) 的 s。如果存在两个这样的 s 的可能值,则选择偶数者。注意,k 是使用基数 radix 表示 s 时的位数,并且 s 不能被 radix 整除。
Note 3

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

Gay, David M. Correctly Rounded Binary-Decimal and Decimal-Binary Conversions. Numerical Analysis, Manuscript 90-10. AT&T Bell Laboratories (Murray Hill, New Jersey). 30 November 1990. 可获取为
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 类型表示整数值。该值可以是任意大小,且不限于特定位宽。通常,除非另有说明,操作被设计为返回基于精确数学的答案。对于二元操作,BigInts 表现为二进制补码二进制字符串,负数被视为在左侧无限设置位。

6.1.6.2.1 BigInt::unaryMinus ( bigint )

The abstract operation BigInt::unaryMinus takes argument bigint (a BigInt) and returns a BigInt. It performs the following steps when called:

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

6.1.6.2.2 BigInt::bitwiseNOT ( bigint )

The abstract operation BigInt::bitwiseNOT takes argument bigint (a BigInt) and returns a BigInt. 它返回 bigint 的一补数。 It performs the following steps when called:

  1. 返回 -bigint - 1

6.1.6.2.3 BigInt::exponentiate ( base, exponent )

The abstract operation BigInt::exponentiate takes arguments base (a BigInt) and exponent (a BigInt) and returns either a normal completion containing a BigInt or a throw completion. It performs the following steps when called:

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

6.1.6.2.4 BigInt::multiply ( x, y )

The abstract operation BigInt::multiply takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

  1. 返回 x × y
Note
即使结果具有比输入大得多的位宽,也会给出精确的数学答案。

6.1.6.2.5 BigInt::divide ( x, y )

The abstract operation BigInt::divide takes arguments x (a BigInt) and y (a BigInt) and returns either a normal completion containing a BigInt or a throw completion. It performs the following steps when called:

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

6.1.6.2.6 BigInt::remainder ( numerator, denominator )

The abstract operation BigInt::remainder takes arguments numerator (a BigInt) and denominator (a BigInt) and returns either a normal completion containing a BigInt or a throw completion. It performs the following steps when called:

  1. 如果 denominator = 0,则抛出 RangeError 异常。
  2. 如果 numerator = 0,则返回 0
  3. quotient(numerator) / (denominator)。
  4. truncatedQuotient(truncate(quotient))。
  5. 返回 numerator - (denominator × truncatedQuotient)。
Note
结果的符号是被除数的符号。

6.1.6.2.7 BigInt::add ( x, y )

The abstract operation BigInt::add takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

  1. 返回 x + y

6.1.6.2.8 BigInt::subtract ( x, y )

The abstract operation BigInt::subtract takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

  1. 返回 x - y

6.1.6.2.9 BigInt::leftShift ( x, y )

The abstract operation BigInt::leftShift takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

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

6.1.6.2.10 BigInt::signedRightShift ( x, y )

The abstract operation BigInt::signedRightShift takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

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

6.1.6.2.11 BigInt::unsignedRightShift ( x, y )

The abstract operation BigInt::unsignedRightShift takes arguments x (a BigInt) and y (a BigInt) and returns a throw completion. It performs the following steps when called:

  1. 抛出 TypeError 异常。

6.1.6.2.12 BigInt::lessThan ( x, y )

The abstract operation BigInt::lessThan takes arguments x (a BigInt) and y (a BigInt) and returns a Boolean. It performs the following steps when called:

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

6.1.6.2.13 BigInt::equal ( x, y )

The abstract operation BigInt::equal takes arguments x (a BigInt) and y (a BigInt) and returns a Boolean. It performs the following steps when called:

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

6.1.6.2.14 BinaryAnd ( x, y )

The abstract operation BinaryAnd takes arguments x (0 or 1) and y (0 or 1) and returns 0 or 1. It performs the following steps when called:

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

6.1.6.2.15 BinaryOr ( x, y )

The abstract operation BinaryOr takes arguments x (0 or 1) and y (0 or 1) and returns 0 or 1. It performs the following steps when called:

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

6.1.6.2.16 BinaryXor ( x, y )

The abstract operation BinaryXor takes arguments x (0 or 1) and y (0 or 1) and returns 0 or 1. It performs the following steps when called:

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

6.1.6.2.17 BigIntBitwiseOp ( op, x, y )

The abstract operation BigIntBitwiseOp takes arguments op (&, ^, or |), x (a BigInt), and y (a BigInt) and returns a BigInt. It performs the following steps when called:

  1. x 设置为 (x)。
  2. y 设置为 (y)。
  3. result 为 0。
  4. shift 为 0。
  5. 重复,直到 (x = 0 或 x = -1) 且 (y = 0 或 y = -1):
    1. xDigitx modulo 2。
    2. yDigity 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. signBitBinaryAnd(x modulo 2, y modulo 2)。
  7. 否则如果 op|,则
    1. signBitBinaryOr(x modulo 2, y modulo 2)。
  8. 否则,
    1. 断言:op^
    2. signBitBinaryXor(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 )

The abstract operation BigInt::bitwiseAND takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

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

6.1.6.2.19 BigInt::bitwiseXOR ( x, y )

The abstract operation BigInt::bitwiseXOR takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

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

6.1.6.2.20 BigInt::bitwiseOR ( x, y )

The abstract operation BigInt::bitwiseOR takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

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

6.1.6.2.21 BigInt::toString ( x, radix )

The abstract operation BigInt::toString takes arguments x (a BigInt) and radix (an integer in the inclusive interval from 2 to 36) and returns a String. 它使用基数为 radix 的位置计数系统,将 x 表示为 String。使用基数 r 表示 BigInt 时所用的数字,按顺序取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个码元。除 0 之外的 BigInts 的表示从不包含前导零。 It performs the following steps when called:

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

6.1.7 Object 类型

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

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

对象的属性使用属性键唯一标识。属性键要么是 String,要么是 Symbol。所有 Strings 和 Symbols,包括空 String,都可作为有效的属性键属性名是作为 String 的属性键

整数索引是一个属性名 n,使得 CanonicalNumericIndexString(n) 返回从 +0𝔽𝔽(253 - 1) 的闭区间内的 integral Number数组索引是一个整数索引 n,使得 CanonicalNumericIndexString(n) 返回从 +0𝔽𝔽(232 - 2) 的闭区间内的 integral Number

Note

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

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

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

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

6.1.7.1 属性特性

本规范使用特性来定义和解释 Object 属性的状态,如 Table 3 所述。除非显式指定,否则每个特性的初始值都是其默认值。

Table 3: Object 属性的特性
特性名称 它出现于哪类属性 值域 默认值 描述
[[Value]] 数据属性 一个 ECMAScript 语言值 undefined 对该属性执行 get 访问时取回的值。
[[Writable]] 数据属性 一个 Boolean false 如果为 false,ECMAScript 代码尝试使用 [[Set]] 改变该属性的 [[Value]] 特性将不会成功。
[[Get]] 访问器属性 一个 Object 或 undefined undefined 如果该值是 Object,则它必须是函数对象。每次对该属性执行 get 访问以取回属性值时,都会以空实参列表调用该函数的 [[Call]] 内部方法(Table 5)。
[[Set]] 访问器属性 一个 Object 或 undefined undefined 如果该值是 Object,则它必须是函数对象。每次对该属性执行 set 访问时,都会以包含被赋值作为唯一实参的实参列表调用该函数的 [[Call]] 内部方法(Table 5)。属性的 [[Set]] 内部方法的效果可以、但并不要求,对该属性后续 [[Get]] 内部方法调用返回的值产生影响。
[[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 异常。

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

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

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

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

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

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

异质对象是不是普通对象的对象。

本规范通过这些对象的内部方法识别不同种类的异质对象。行为上等价于某种特定异质对象(例如 Array 异质对象绑定函数异质对象)的对象,如果没有为该种类指定的相同内部方法集合,则不会被识别为该种异质对象

Table 4 以及其他类似表格中的“Signature”列描述每个内部方法的调用模式。调用模式总是包含一个带括号的描述性形参名列表。如果形参名与 ECMAScript 类型名相同,则该名称描述形参值所需的类型。如果内部方法显式返回一个值,则其形参列表后跟符号“→”和返回值的类型名。签名中使用的类型名指代条款 6 中定义的类型,并由以下附加名称扩充。“any”表示该值可以是任何 ECMAScript 语言类型

除形参之外,内部方法始终能够访问作为方法调用目标的对象。

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

Table 4: 基本内部方法
内部方法 签名 描述
[[GetPrototypeOf]] ( ) Object | Null 确定为此对象提供继承属性的对象。null 值表示没有继承属性。
[[SetPrototypeOf]] (Object | Null) Boolean 将此对象与另一个提供继承属性的对象相关联。传入 null 表示没有继承属性。返回 true 表示操作成功完成,或返回 false 表示操作未成功。
[[IsExtensible]] ( ) Boolean 确定是否允许向此对象添加额外属性。
[[PreventExtensions]] ( ) Boolean 控制是否可以向此对象添加新属性。如果操作成功则返回 true,如果操作不成功则返回 false
[[GetOwnProperty]] (propertyKey) Undefined | Property Descriptor 返回此对象中键为 propertyKey 的自有属性的 Property Descriptor;如果不存在这样的属性,则返回 undefined
[[DefineOwnProperty]] (propertyKey, propertyDesc) Boolean 创建或变更键为 propertyKey 的自有属性,使其具有 propertyDesc 描述的状态。如果该属性被成功创建/更新,则返回 true;如果该属性无法被创建或更新,则返回 false
[[HasProperty]] (propertyKey) Boolean 返回一个 Boolean 值,指示此对象是否已经具有键为 propertyKey 的自有属性或继承属性。
[[Get]] (propertyKey, receiver) any 从此对象返回键为 propertyKey 的属性的值。如果必须执行任何 ECMAScript 代码以取回该属性值,则在求值该代码时使用 receiver 作为 this 值。
[[Set]] (propertyKey, value, receiver) Boolean 将键为 propertyKey 的属性的值设置为 value。如果必须执行任何 ECMAScript 代码以设置该属性值,则在求值该代码时使用 receiver 作为 this 值。如果属性值被设置则返回 true,如果无法设置则返回 false
[[Delete]] (propertyKey) Boolean 从此对象移除键为 propertyKey 的自有属性。如果该属性未被删除且仍然存在,则返回 false。如果该属性已被删除或不存在,则返回 true
[[OwnPropertyKeys]] ( ) List of property keys 返回一个 List,其元素是该对象的所有自有属性键

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

Table 5: 函数对象的附加基本内部方法
内部方法 签名 描述
[[Call]] (any, a List of any) any 执行与此对象相关联的代码。通过函数调用表达式调用。该内部方法的实参是一个 this 值和一个 List,其元素是调用表达式传给函数的实参。实现此内部方法的对象是可调用的
[[Construct]] (a List of any, Object) Object 创建一个对象。通过 new 运算符或 super 调用来调用。该内部方法的第一个实参是一个 List,其元素是构造函数调用或 super 调用的实参。第二个实参是 new 运算符最初应用到的对象。实现此内部方法的对象称为构造函数函数对象不一定是构造函数,这类非构造函数函数对象没有 [[Construct]] 内部方法。

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

6.1.7.3 基本内部方法的不变式

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

任何实现提供的异质对象也必须为这些对象维护这些不变式。违反这些不变式可能导致 ECMAScript 代码具有不可预测行为并产生安全问题。然而,违反这些不变式绝不能危及实现的内存安全。

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

定义:

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

返回值:

任何内部方法返回的值必须是一个 Completion Record,具有以下二者之一:

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

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

[[GetPrototypeOf]] ( )

  • 正常返回类型要么是 Object,要么是 Null。
  • 如果 target 是不可扩展的,并且 [[GetPrototypeOf]] 返回值 proto,则对 [[GetPrototypeOf]] 的任何未来调用都应返回与 proto SameValue 的值。
Note 2

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

[[SetPrototypeOf]] ( proto )

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

[[IsExtensible]] ( )

  • 正常返回类型是 Boolean。
  • 如果 [[IsExtensible]] 返回 false,则该 target 上未来对 [[IsExtensible]] 的所有调用都必须返回 false

[[PreventExtensions]] ( )

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

[[GetOwnProperty]] ( propertyKey )

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

作为第三个不变式的结果,如果某属性被描述为数据属性,并且它可能随时间返回不同的值,则即使没有通过其他基本内部方法暴露改变该值的机制,[[Writable]][[Configurable]] 特性之一或二者也必须为 true

[[DefineOwnProperty]] ( propertyKey, propertyDesc )

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

[[HasProperty]] ( propertyKey )

  • 正常返回类型是 Boolean。
  • 如果 propertyKey 先前已被观察为 target 的不可配置自有数据属性访问器属性,则 [[HasProperty]] 必须返回 true

[[Get]] ( propertyKey, receiver )

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

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

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

[[Delete]] ( propertyKey )

  • 正常返回类型是 Boolean。
  • 如果 propertyKey 先前已被观察为 target 的不可配置自有数据属性访问器属性,则 [[Delete]] 必须返回 false

[[OwnPropertyKeys]] ( )

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

[[Call]] ( )

[[Construct]] ( )

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

6.1.7.4 众所周知的内在对象

众所周知的内在是由本规范的算法显式引用的内置对象,并且它们通常具有 realm 特有的身份。除非另有规定,每个内在对象实际上对应于一组相似的对象,每个 realm 一个。

在本规范中,诸如 %name% 的引用表示与当前 realm 相关联、对应于该名称的内在对象。诸如 %name.a.b% 的引用表示,好像在任何 ECMAScript 代码被求值之前,访问了内在对象 %name% 的 "a" 属性值的 "b" 属性。当前 realm 及其内在的确定在 9.4 中描述。众所周知的内在列于 Table 6

Table 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% async function 对象的 构造函数27.10.1
%AsyncGeneratorFunction% async generator function 对象的 构造函数27.7.1
%AsyncGeneratorPrototype% async generator 对象的原型(27.9
%AsyncIteratorPrototype% 所有标准内置 async iterator 对象都间接继承自的对象
%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% generator function 对象的 构造函数27.6.1
%GeneratorPrototype% generator 对象的原型(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% 所有 typed 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 返回的 wrapped iterator 对象的原型(27.1.3.2.2.1
Note

Table 103 中还有附加条目。

6.2 ECMAScript 规范类型

规范类型对应于在算法中用于描述 ECMAScript 语言构造和 ECMAScript 语言类型语义的元值。规范类型包括 Reference RecordListCompletion RecordProperty DescriptorEnvironment RecordAbstract ClosureData Block。规范类型值是规范工件,不一定对应于 ECMAScript 实现中的任何特定实体。规范类型值可用于描述 ECMAScript 表达式求值的中间结果,但这类值不能作为对象属性或 ECMAScript 语言变量的值存储。

6.2.1 Enum 规范类型

Enums 是规范内部的值,不能从 ECMAScript 代码中直接观察到。Enums 使用 sans-serif 字体以 upper kebab case 表示。例如,Completion Record[[Type]] 字段会取 normalreturnthrow 之类的值。Enums 除名称之外没有任何特性。enum 的名称除了将其与其他 enums 区分开之外没有其他目的,并且不暗示其在上下文中的用法或含义。

6.2.2 List 和 Record 规范类型

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

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

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

在本规范中,短语“AB、... 的列表连接”(其中每个实参都是可能为空的 List)表示一个新的 List 值,其元素是每个实参的元素(按顺序)的连接(按顺序)。

当应用于 Strings 的 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 类型的值是简单的元素集合,其中没有元素出现超过一次。可以向 Sets 添加元素,也可以从 Sets 中移除元素。Sets 可以彼此求并集、交集或差集。

Relation 类型用于解释 Sets 上的约束。Relation 类型的值是其值域中值的有序对的 Sets。例如,Memory 事件上的 Relation 是 Memory 事件的有序对集合。对于 Relation R 以及 R 的值域中的两个值 aba R b 是“有序对 (a, b) 是 R 的成员”的简写。当某个 Relation 是满足某些条件的最小 Relation 时,它就是相对于这些条件的最小 Relation

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

  • 对于 R 的域中的所有 abc

    • 并非 a R a,并且
    • 如果 a R bb R c,则 a R c
Note 1

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

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

  • 对于 R 的域中的所有 abc

    • ab,或 a R b,或 b R a,并且
    • 并非 a R a,并且
    • 如果 a R bb R c,则 a R c
Note 2

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

6.2.4 Completion Record 规范类型

Completion Record 规范类型用于解释值和控制流的运行时传播,例如执行非局部控制转移的语句(breakcontinuereturnthrow)的行为。

Completion Records 具有 Table 7 中定义的字段。

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

以下简写术语有时用于指代 Completion Records。

  • 正常完成指任何 [[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 )

The abstract operation NormalCompletion takes argument value (any value except a Completion Record) and returns a normal completion. It performs the following steps when called:

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

6.2.4.2 ThrowCompletion ( value )

The abstract operation ThrowCompletion takes argument value (an ECMAScript language value) and returns a throw completion. It performs the following steps when called:

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

6.2.4.3 ReturnCompletion ( value )

The abstract operation ReturnCompletion takes argument value (an ECMAScript language value) and returns a return completion. It performs the following steps when called:

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

6.2.4.4 UpdateEmpty ( completionRecord, value )

The abstract operation UpdateEmpty takes arguments completionRecord (a Completion Record) and value (any value except a Completion Record) and returns a Completion Record. It performs the following steps when called:

  1. 断言:如果 completionRecordreturn 完成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 类型用于解释 deletetypeof、赋值运算符、super 关键字以及其他语言特性的行为。例如,赋值的左侧操作数预期会产生 Reference Record。

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

Table 8: Reference Record 字段
字段名 含义
[[Base]] ECMAScript 语言值Environment Recordunresolvable 保存绑定的值或 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 Records:

6.2.5.1 IsPropertyReference ( refRecord )

The abstract operation IsPropertyReference takes argument refRecord (a Reference Record) and returns a Boolean. It performs the following steps when called:

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

6.2.5.2 IsUnresolvableReference ( refRecord )

The abstract operation IsUnresolvableReference takes argument refRecord (a Reference Record) and returns a Boolean. It performs the following steps when called:

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

6.2.5.3 IsSuperReference ( refRecord )

The abstract operation IsSuperReference takes argument refRecord (a Reference Record) and returns a Boolean. It performs the following steps when called:

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

6.2.5.4 IsPrivateReference ( refRecord )

The abstract operation IsPrivateReference takes argument refRecord (a Reference Record) and returns a Boolean. It performs the following steps when called:

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

6.2.5.5 GetValue ( refRecord )

The abstract operation GetValue takes argument refRecord (a Reference Record or an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  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. baserefRecord.[[Base]]
  5. 断言:baseEnvironment Record
  6. 返回 ? base.GetBindingValue(refRecord.[[ReferencedName]], refRecord.[[Strict]])(参见 9.1)。
Note

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

6.2.5.6 PutValue ( refRecord, value )

The abstract operation PutValue takes arguments refRecord (a Reference Record or an ECMAScript language value) and value (an ECMAScript language value) and returns either a normal completion containing unused or an abrupt completion. It performs the following steps when called:

  1. 如果 refRecord 不是 Reference Record,则抛出 ReferenceError 异常。
  2. 如果 IsUnresolvableReference(refRecord) 是 true,则
    1. 如果 refRecord.[[Strict]]true,则抛出 ReferenceError 异常。
    2. globalObjGetGlobalObject()。
    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. 如果 succeededfalserefRecord.[[Strict]]true,则抛出 TypeError 异常。
    6. 返回 unused
  4. baserefRecord.[[Base]]
  5. 断言:baseEnvironment Record
  6. 返回 ? base.SetMutableBinding(refRecord.[[ReferencedName]], value, refRecord.[[Strict]])(参见 9.1)。
Note

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

6.2.5.7 GetThisValue ( refRecord )

The abstract operation GetThisValue takes argument refRecord (a Reference Record) and returns an ECMAScript language value. It performs the following steps when called:

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

6.2.5.8 InitializeReferencedBinding ( refRecord, value )

The abstract operation InitializeReferencedBinding takes arguments refRecord (a Reference Record) and value (an ECMAScript language value) and returns either a normal completion containing unused or an abrupt completion. It performs the following steps when called:

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

6.2.5.9 MakePrivateReference ( baseValue, privateIdentifier )

The abstract operation MakePrivateReference takes arguments baseValue (an ECMAScript language value) and privateIdentifier (a String) and returns a Reference Record. It performs the following steps when called:

  1. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  2. 断言:privateEnv 不是 null
  3. privateNameResolvePrivateIdentifier(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 records 字面量描述的模式名称是“PropertyDescriptor”。

Property Descriptor 值可以根据某些字段的存在或使用进一步分类为数据 Property Descriptors 和访问器 Property Descriptors。数据 Property Descriptor 是包含名为 [[Value]][[Writable]] 的任一字段的描述符。访问器 Property Descriptor 是包含名为 [[Get]][[Set]] 的任一字段的描述符。任何 Property Descriptor 都可以具有名为 [[Enumerable]][[Configurable]] 的字段。Property Descriptor 值不能既是数据 Property Descriptor 又是访问器 Property Descriptor;但是,它可以二者都不是(在这种情况下它是通用 Property Descriptor)。完整填充的 Property Descriptor是访问器 Property Descriptor 或数据 Property Descriptor,并且具有 Table 3 中定义的所有对应字段。

以下抽象操作在本规范中用于操作 Property Descriptor 值:

6.2.6.1 IsAccessorDescriptor ( propertyDesc )

The abstract operation IsAccessorDescriptor takes argument propertyDesc (a Property Descriptor) and returns a Boolean. It performs the following steps when called:

  1. 如果 propertyDesc 具有 [[Get]] 字段,则返回 true
  2. 如果 propertyDesc 具有 [[Set]] 字段,则返回 true
  3. 返回 false

6.2.6.2 IsDataDescriptor ( propertyDesc )

The abstract operation IsDataDescriptor takes argument propertyDesc (a Property Descriptor) and returns a Boolean. It performs the following steps when called:

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

6.2.6.3 IsGenericDescriptor ( propertyDesc )

The abstract operation IsGenericDescriptor takes argument propertyDesc (a Property Descriptor) and returns a Boolean. It performs the following steps when called:

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

6.2.6.4 FromPropertyDescriptor ( propertyDesc )

The abstract operation FromPropertyDescriptor takes argument propertyDesc (a Property Descriptor or undefined) and returns an Object or undefined. It performs the following steps when called:

  1. 如果 propertyDescundefined,则返回 undefined
  2. objOrdinaryObjectCreate(%Object.prototype%)。
  3. 断言:obj 是一个可扩展的普通对象,且没有自有属性。
  4. 如果 propertyDesc 具有 [[Value]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "value", propertyDesc.[[Value]])。
  5. 如果 propertyDesc 具有 [[Writable]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "writable", propertyDesc.[[Writable]])。
  6. 如果 propertyDesc 具有 [[Get]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "get", propertyDesc.[[Get]])。
  7. 如果 propertyDesc 具有 [[Set]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "set", propertyDesc.[[Set]])。
  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 )

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

  1. 如果 obj 不是 Object,则抛出 TypeError 异常。
  2. propertyDesc 为一个新的 Property Descriptor,其最初没有字段。
  3. hasEnumerable 为 ? HasProperty(obj, "enumerable")。
  4. 如果 hasEnumerabletrue,则
    1. enumerableToBoolean(? Get(obj, "enumerable")).
    2. propertyDesc.[[Enumerable]] 设置为 enumerable
  5. hasConfigurable 为 ? HasProperty(obj, "configurable")。
  6. 如果 hasConfigurabletrue,则
    1. configurableToBoolean(? Get(obj, "configurable")).
    2. propertyDesc.[[Configurable]] 设置为 configurable
  7. hasValue 为 ? HasProperty(obj, "value")。
  8. 如果 hasValuetrue,则
    1. value 为 ? Get(obj, "value")。
    2. propertyDesc.[[Value]] 设置为 value
  9. hasWritable 为 ? HasProperty(obj, "writable")。
  10. 如果 hasWritabletrue,则
    1. writableToBoolean(? Get(obj, "writable")).
    2. propertyDesc.[[Writable]] 设置为 writable
  11. hasGet 为 ? HasProperty(obj, "get")。
  12. 如果 hasGettrue,则
    1. getter 为 ? Get(obj, "get")。
    2. 如果 IsCallable(getter) 是 falsegetter 不是 undefined,则抛出 TypeError 异常。
    3. propertyDesc.[[Get]] 设置为 getter
  13. hasSet 为 ? HasProperty(obj, "set")。
  14. 如果 hasSettrue,则
    1. setter 为 ? Get(obj, "set")。
    2. 如果 IsCallable(setter) 是 falsesetter 不是 undefined,则抛出 TypeError 异常。
    3. propertyDesc.[[Set]] 设置为 setter
  15. 如果 propertyDesc 具有 [[Get]] 字段或 propertyDesc 具有 [[Set]] 字段,则
    1. 如果 propertyDesc 具有 [[Value]] 字段或 propertyDesc 具有 [[Writable]] 字段,则抛出 TypeError 异常。
  16. 返回 propertyDesc

6.2.6.6 CompletePropertyDescriptor ( propertyDesc )

The abstract operation CompletePropertyDescriptor takes argument propertyDesc (a Property Descriptor) and returns unused. It performs the following steps when called:

  1. likeRecord { [[Value]]: undefined, [[Writable]]: false, [[Get]]: undefined, [[Set]]: undefined, [[Enumerable]]: false, [[Configurable]]: false }。
  2. 如果 IsGenericDescriptor(propertyDesc) 是 trueIsDataDescriptor(propertyDesc) 是 true,则
    1. 如果 propertyDesc 不具有 [[Value]] 字段,则将 propertyDesc.[[Value]] 设置为 like.[[Value]]
    2. 如果 propertyDesc 不具有 [[Writable]] 字段,则将 propertyDesc.[[Writable]] 设置为 like.[[Writable]]
  3. 否则,
    1. 如果 propertyDesc 不具有 [[Get]] 字段,则将 propertyDesc.[[Get]] 设置为 like.[[Get]]
    2. 如果 propertyDesc 不具有 [[Set]] 字段,则将 propertyDesc.[[Set]] 设置为 like.[[Set]]
  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 Closures 是元值,并使用函数应用样式调用,例如 closure(arg1, arg2)。与抽象操作一样,调用会执行 Abstract Closure 所描述的算法步骤。

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

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

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

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

6.2.9 Data Blocks

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

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

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

Shared Data Blocks 的语义由内存模型使用 Shared Data Block 事件定义。下面的抽象操作引入 Shared Data Block 事件,并作为求值语义与内存模型事件语义之间的接口。事件形成一个候选执行,内存模型将其作为过滤器作用于该候选执行。完整语义请参阅内存模型

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

以下抽象操作在本规范中用于操作 Data Block 值:

6.2.9.1 CreateByteDataBlock ( size )

The abstract operation CreateByteDataBlock takes argument size (a non-negative integer) and returns either a normal completion containing a Data Block or a throw completion. It performs the following steps when called:

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

6.2.9.2 CreateSharedByteDataBlock ( size )

The abstract operation CreateSharedByteDataBlock takes argument size (a non-negative integer) and returns either a normal completion containing a Shared Data Block or a throw completion. It performs the following steps when called:

  1. dataBlock 为一个由 size 个字节组成的新 Shared Data Block 值。如果无法创建这样的 Shared Data Block,则抛出 RangeError 异常。
  2. agentRecord周围 agentAgent Record
  3. executionagentRecord.[[CandidateExecution]]
  4. eventsRecordexecution.[[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 )

The abstract operation CopyDataBlockBytes takes arguments toBlock (a Data Block or a Shared Data Block), toIndex (a non-negative integer), fromBlock (a Data Block or a Shared Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns unused. It performs the following steps when called:

  1. 断言:fromBlocktoBlock 是不同的值。
  2. fromSizefromBlock 中的字节数。
  3. 断言:fromIndex + countfromSize
  4. toSizetoBlock 中的字节数。
  5. 断言:toIndex + counttoSize
  6. 重复,当 count > 0 时:
    1. 如果 fromBlockShared Data Block,则
      1. agentRecord周围 agentAgent Record
      2. executionagentRecord.[[CandidateExecution]]
      3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
      4. bytes 为一个 List,其唯一元素是一个非确定性选择的字节值
      5. 注记:在实现中,bytes 是底层硬件上非原子读指令的结果。该非确定性是内存模型的语义规定,用于描述弱一致性硬件的可观察行为。
      6. readEventReadSharedMemory { [[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. 如果 toBlockShared 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 Descriptors 不用于私有元素,私有字段的行为类似于不可配置、不可枚举、可写的数据属性,私有方法的行为类似于不可配置、不可枚举、不可写的数据属性,而私有访问器的行为类似于不可配置、不可枚举的访问器属性

PrivateElement 类型的值是 Record 值,其字段由 Table 9 定义。这类值称为 PrivateElements

Table 9: PrivateElement 字段
字段名 其存在所对应的 [[Kind]] 字段值 含义
[[Key]] 全部 Private Name 字段、方法或访问器的名称。
[[Kind]] 全部 field, method, or accessor 元素的种类。
[[Value]] fieldmethod ECMAScript 语言值 字段的值。
[[Get]] accessor 函数对象undefined 私有访问器的 getter。
[[Set]] accessor 函数对象undefined 私有访问器的 setter。

6.2.11 ClassFieldDefinition Record 规范类型

ClassFieldDefinition 类型是用于类字段规范的 Record

ClassFieldDefinition 类型的值是 Record 值,其字段由 Table 10 定义。这类值称为 ClassFieldDefinition Records

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

6.2.12 Private Names

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

6.2.13 ClassStaticBlockDefinition Record 规范类型

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

ClassStaticBlockDefinition Records 具有 Table 11 中列出的字段。

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