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 程序中的文本数据,此时每个元素都被视为一个 UTF-16 码元值。每个元素被认为在序列中占据一个位置,这些位置用非负整数索引。第一个元素(如果有)索引为 0,第二个元素索引为 1,依此类推。String 的长度即其包含的元素(即 16 位值)数。空字符串长度为零,因此不含任何元素。

未解释字符串内容的 ECMAScript 操作不施加进一步语义。解释字符串值的操作则将每个元素视为单个 UTF-16 码元。然而,ECMAScript 不限制这些码元的值或相互关系,因此进一步将字符串内容解释为 UTF-16 编码的 Unicode 码点序列时,必须考虑不规范的子序列。此类操作会对数值在闭区间 0xD800 到 0xDBFF 的码元(Unicode 标准定义为 前导代理,或正式称为 高代理码元)以及闭区间 0xDC00 到 0xDFFF 的码元(定义为 后导代理,或正式称为 低代理码元)做如下处理:

可使用 String.prototype.normalize(见 22.1.3.15)显式规范化字符串值。String.prototype.localeCompare(见 22.1.3.12)会在内部规范化字符串值,但其它操作不会隐式规范化其操作的字符串。操作结果除非另有说明,否则不具备语言或区域敏感性。

Note

该设计的理由是使字符串实现尽量简单且高效。如果 ECMAScript 源文本为标准化形式 C,则字符串字面量也一定是标准化的,只要其中不包含 Unicode 转义序列。

在本规范中,“the string-concatenation of A, B, ...”(每个参数为字符串值、码元或码元序列)表示顺序连接每个参数的码元后得到的字符串值。

“the substring of S from inclusiveStart to exclusiveEnd”(S 为字符串值或码元序列,inclusiveStartexclusiveEnd 为整数)表示从索引 inclusiveStart 到紧邻索引 exclusiveEnd 之前的顺序码元组成的字符串值(当 inclusiveStart = exclusiveEnd 时为空字符串)。若省略 "to" 后缀,则 exclusiveEndS 的长度。

the ASCII word characters”表示如下字符串值,仅包含 Unicode 基本拉丁区的所有字母和数字以及 U+005F(下划线):
"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. lenstring 的长度。
  2. 如果 searchValue 是空字符串且 fromIndexlen,返回 fromIndex
  3. searchLensearchValue 的长度。
  4. 对每个满足 fromIndexilen - searchLen 的整数 i,按升序执行
    1. candidatestringii + searchLen 的子串。
    2. 如果 candidate 等于 searchValue,返回 i
  5. 返回 not-found
Note 1

如果 searchValue 是空字符串且 fromIndexstring 的长度,则返回 fromIndex。空字符串在字符串的每个位置都可找到,包括最后一个码元之后。

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. lenstring 的长度。
  2. searchLensearchValue 的长度。
  3. Assert: fromIndex + searchLenlen
  4. 对每个满足 0 ≤ ifromIndex 的整数 i,按降序执行
    1. candidatestringii + searchLen 的子串。
    2. 如果 candidate 等于 searchValue,返回 i
  5. 返回 not-found
Note

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

6.1.5 Symbol 类型

Symbol 类型是所有可用作对象属性键的非字符串值的集合(6.1.7)。

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

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

6.1.5.1 知名 Symbol

知名 Symbol 是规范算法明确引用的内建 Symbol 值。它们通常用作属性键,这些属性的值作为规范算法的扩展点。除非另有说明,知名 Symbol 在所有 realm9.3)间共享。

在本规范中,知名 Symbol 使用标准的 内在记号引用,其中内在对象为 Table 1 所列值之一。

Note
规范的早期版本采用 @@name 记号,而本版本采用 %Symbol.name%。具体包括:@@asyncIterator、@@hasInstance、@@isConcatSpreadable、@@iterator、@@match、@@matchAll、@@replace、@@search、@@species、@@split、@@toPrimitive、@@toStringTag 和 @@unscopables。
Table 1: 知名 Symbol
规范名称 [[Description]] 值及用途
%Symbol.asyncIterator% "Symbol.asyncIterator" 返回对象默认异步迭代器的方法。由 for-await-of 语句语义调用。
%Symbol.hasInstance% "Symbol.hasInstance" 判断构造函数对象是否识别某对象为其实例的方法。由 instanceof 运算符语义调用。
%Symbol.isConcatSpreadable% "Symbol.isConcatSpreadable" 一个布尔属性,若为 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" 用于创建对象默认字符串描述的字符串属性。通过内建方法 Object.prototype.toString 访问。
%Symbol.unscopables% "Symbol.unscopables" 一个对象属性,其自身和继承的属性名是关联对象的 with 环境绑定中被排除的属性名

6.1.6 数值类型

ECMAScript 有两种内建数值类型:Number 和 BigInt。以下抽象操作定义于这些数值类型之上。“结果”列显示返回类型,同时指明部分调用可能返回异常完成

Table 2: 数值类型操作
操作 示例源码 在...的求值语义中调用 结果
Number::unaryMinus -x 一元 - 运算符 (Unary - Operator) Number
BigInt::unaryMinus BigInt
Number::bitwiseNOT ~x 按位取反运算符 (Bitwise NOT Operator ~) Number
BigInt::bitwiseNOT BigInt
Number::exponentiate x ** y 幂运算符 (Exponentiation Operator) and Math.pow ( base, exponent ) Number
BigInt::exponentiate 返回正常完成的 BigInt 或抛出完成
Number::multiply x * y 乘法类运算符 (Multiplicative Operators) Number
BigInt::multiply BigInt
Number::divide x / y 乘法类运算符 (Multiplicative Operators) Number
BigInt::divide 返回正常完成的 BigInt 或抛出完成
Number::remainder x % y 乘法类运算符 (Multiplicative Operators) Number
BigInt::remainder 返回正常完成的 BigInt 或抛出完成
Number::add x ++
++ x
x + y
后缀自增运算符 (Postfix Increment Operator), 前缀自增运算符 (Prefix Increment Operator), and 加法运算符 (The Addition Operator +) Number
BigInt::add BigInt
Number::subtract x --
-- x
x - y
后缀自减运算符 (Postfix Decrement Operator), 前缀自减运算符 (Prefix Decrement Operator), and 减法运算符 (The Subtraction Operator -) Number
BigInt::subtract BigInt
Number::leftShift x << y 左移运算符 (The Left Shift Operator <<) Number
BigInt::leftShift BigInt
Number::signedRightShift x >> y 带符号右移运算符 (The Signed Right Shift Operator >>) Number
BigInt::signedRightShift BigInt
Number::unsignedRightShift x >>> y 无符号右移运算符 (The Unsigned Right Shift Operator >>>) Number
BigInt::unsignedRightShift 抛出完成
Number::lessThan x < y
x > y
x <= y
x >= y
关系运算符 (Relational Operators), via IsLessThan ( x, y, LeftFirst ) Boolean 或 undefined(用于无序输入)
BigInt::lessThan Boolean
Number::equal x == y
x != y
x === y
x !== y
相等运算符 (Equality Operators), via IsStrictlyEqual ( x, y ) Boolean
BigInt::equal
Number::sameValue Object.is(x, y) 对象内部方法, via SameValue ( x, y ), 用于测试精确值相等性 Boolean
Number::sameValueZero [x].includes(y) via SameValueZero ( x, y ), 用于测试值相等性,忽略 +0𝔽-0𝔽 的区别,如 Array、Map 和 Set 方法 Boolean
Number::bitwiseAND x & y 二元按位运算符 (Binary Bitwise Operators) Number
BigInt::bitwiseAND BigInt
Number::bitwiseXOR x ^ y Number
BigInt::bitwiseXOR BigInt
Number::bitwiseOR x | y Number
BigInt::bitwiseOR BigInt
Number::toString String(x) 多种表达式和内建函数,via ToString ( argument ) 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 754-2019 binary64 双精度浮点数值,遵循 IEEE 二进制浮点运算标准。不同于 IEEE 标准的 9,007,199,254,740,990 个 NaN 值(即 253 - 2),ECMAScript 将这些 NaN 都表示为一个特殊的 NaN 值。(注意,NaN 值可由表达式 NaN 得到。)在某些实现中,外部代码可能能区分不同的 NaN,但这种行为由实现定义;对于 ECMAScript 代码,所有 NaN 都无法区分。

Note

将 Number 值存入 ArrayBuffer(参见 25.1)或 SharedArrayBuffer(参见 25.2)后观察到的比特模式,不一定与 ECMAScript 内部表示该 Number 值的方式一致。

还有两个特殊值,称为 正无穷负无穷。为了简便,分别用符号 +∞𝔽-∞𝔽 表示。(注意,这两个无限值可由表达式 +Infinity(或简写为 Infinity)和 -Infinity 得到。)

其余 18,437,736,874,454,810,624 个值(即 264 - 253)称为 有限数值。这些数值一半为正,一半为负,对于每一个有限的正数,都有一个相同绝对值的负数。

注意,存在 正零负零。为了简便,分别用符号 +0𝔽-0𝔽 表示。(注意,这两个零值可由表达式 +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 为奇数,则称其为 奇有效数字;否则为 偶有效数字

在本规范中,“x 的 Number 值”表示 x 是某个精确的数学实数(甚至可能是无理数如 π),其 Number 值按如下方式选取:取所有有限 Number 类型值的集合,去掉 -0𝔽 并加上两个 Number 类型不可表示的值,即 21024(即 +1 × 253 × 2971)和 -21024(即 -1 × 253 × 2971)。选取与 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 ( x )

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

  1. 如果 xNaN,返回 NaN
  2. 返回 x 的相反数;即生成一个数值,大小相同,符号相反。

6.1.6.1.2 Number::bitwiseNOT ( x )

The abstract operation Number::bitwiseNOT takes argument x (一个 Number) and returns 一个整数 Number. It performs the following steps when called:

  1. oldValue 为 ! ToInt32(x)。
  2. 返回 oldValue 的按位取反。结果的数学值正好能表示为一个 32 位补码二进制串。

6.1.6.1.3 Number::exponentiate ( base, exponent )

The abstract operation Number::exponentiate takes arguments base (一个 Number) and exponent (一个 Number) and returns 一个 Number. It performs the following steps when called:

  1. 如果 exponentNaN,返回 NaN
  2. 如果 exponent+0𝔽-0𝔽,返回 1𝔽
  3. 如果 baseNaN,返回 NaN
  4. 如果 base+∞𝔽
    1. 如果 exponent > +0𝔽,返回 +∞𝔽;否则返回 +0𝔽
  5. 如果 base-∞𝔽
    1. 如果 exponent > +0𝔽
      1. 如果 exponent 是奇数整数 Number,返回 -∞𝔽;否则返回 +∞𝔽
    2. 否则:
      1. 如果 exponent 是奇数整数 Number,返回 -0𝔽;否则返回 +0𝔽
  6. 如果 base+0𝔽
    1. 如果 exponent > +0𝔽,返回 +0𝔽;否则返回 +∞𝔽
  7. 如果 base-0𝔽
    1. 如果 exponent > +0𝔽
      1. 如果 exponent 是奇数整数 Number,返回 -0𝔽;否则返回 +0𝔽
    2. 否则:
      1. 如果 exponent 是奇数整数 Number,返回 -∞𝔽;否则返回 +∞𝔽
  8. 断言:base有限值且不是 +0𝔽 也不是 -0𝔽
  9. 如果 exponent+∞𝔽
    1. 如果 abs((base)) > 1,返回 +∞𝔽
    2. 如果 abs((base)) = 1,返回 NaN
    3. 如果 abs((base)) < 1,返回 +0𝔽
  10. 如果 exponent-∞𝔽
    1. 如果 abs((base)) > 1,返回 +0𝔽
    2. 如果 abs((base)) = 1,返回 NaN
    3. 如果 abs((base)) < 1,返回 +∞𝔽
  11. 断言:exponent有限值且不是 +0𝔽 也不是 -0𝔽
  12. 如果 base < -0𝔽exponent 不是整数 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 (一个 Number) and y (一个 Number) and returns 一个 Number. It performs the following steps when called:

  1. 如果 xyNaN,返回 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 (一个 Number) and y (一个 Number) and returns 一个 Number. It performs the following steps when called:

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

6.1.6.1.6 Number::remainder ( n, d )

The abstract operation Number::remainder takes arguments n (一个 Number) and d (一个 Number) and returns 一个 Number. It performs the following steps when called:

  1. 如果 ndNaN,返回 NaN
  2. 如果 n+∞𝔽-∞𝔽,返回 NaN
  3. 如果 d+∞𝔽-∞𝔽,返回 n
  4. 如果 d+0𝔽-0𝔽,返回 NaN
  5. 如果 n+0𝔽-0𝔽,返回 n
  6. 断言:nd 都是有限且非零值。
  7. quotient(n) / (d)。
  8. qtruncate(quotient)。
  9. r(n) - ((d) × q)。
  10. 如果 r = 0 且 n < -0𝔽,返回 -0𝔽
  11. 返回 𝔽(r)。
Note 1

C 和 C++ 的余数运算符只接受整数操作数;而 ECMAScript 也接受浮点数操作数。

Note 2
浮点数余数运算 % 的结果与 IEEE 754-2019 中定义的“余数”操作不同。IEEE 的余数操作基于四舍五入除法,而非截断除法,因此行为不同于通常的 整数 余数运算符。ECMAScript 定义 % 运算针对浮点数时的行为类似于 Java 整数 余数运算符;可与 C 库函数 fmod 作比较。

6.1.6.1.7 Number::add ( x, y )

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

  1. 如果 xyNaN,返回 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 (一个 Number) and y (一个 Number) and returns 一个 Number. 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 (一个 Number) and y (一个 Number) and returns 一个整数 Number. It performs the following steps when called:

  1. lNum 为 ! ToInt32(x)。
  2. rNum 为 ! ToUint32(y)。
  3. shiftCount(rNum) 模 32。
  4. 返回将 lNum 左移 shiftCount 位的结果。结果的数学值正好能表示为 32 位补码二进制串。

6.1.6.1.10 Number::signedRightShift ( x, y )

The abstract operation Number::signedRightShift takes arguments x (一个 Number) and y (一个 Number) and returns 一个整数 Number. It performs the following steps when called:

  1. lNum 为 ! ToInt32(x)。
  2. rNum 为 ! ToUint32(y)。
  3. shiftCount(rNum) 模 32。
  4. 返回将 lNum 进行符号扩展右移 shiftCount 位的结果。最高位会被扩展。结果的数学值正好能表示为 32 位补码二进制串。

6.1.6.1.11 Number::unsignedRightShift ( x, y )

The abstract operation Number::unsignedRightShift takes arguments x (一个 Number) and y (一个 Number) and returns 一个整数 Number. It performs the following steps when called:

  1. lNum 为 ! ToUint32(x)。
  2. rNum 为 ! ToUint32(y)。
  3. shiftCount(rNum) 模 32。
  4. 返回将 lNum 进行零填充右移 shiftCount 位的结果。空出的位用零填充。结果的数学值正好能表示为 32 位无符号二进制串。

6.1.6.1.12 Number::lessThan ( x, y )

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

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

6.1.6.1.13 Number::equal ( x, y )

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

  1. 如果 xNaN,返回 false
  2. 如果 yNaN,返回 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 )

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

  1. 如果 xy 都是 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 )

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

  1. 如果 xy 都是 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 )

The abstract operation NumberBitwiseOp takes arguments op (&, ^, 或 |), x (一个 Number), and y (一个 Number) and returns 一个整数 Number. It performs the following steps when called:

  1. lNum 为 ! ToInt32(x)。
  2. rNum 为 ! ToInt32(y)。
  3. lBits 为表示 (lNum) 的 32 位补码二进制串。
  4. rBits 为表示 (rNum) 的 32 位补码二进制串。
  5. 如果 op&
    1. result 为对 lBitsrBits 应用按位与操作的结果。
  6. 否则如果 op^
    1. result 为对 lBitsrBits 应用按位异或操作的结果。
  7. 否则:
    1. 断言 op|
    2. result 为对 lBitsrBits 应用按位或操作的结果。
  8. 返回由 32 位补码二进制串 result 表示的整数的 Number 值。

6.1.6.1.17 Number::bitwiseAND ( x, y )

The abstract operation Number::bitwiseAND takes arguments x (一个 Number) and y (一个 Number) and returns 一个整数 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 (一个 Number) and y (一个 Number) and returns 一个整数 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 (一个 Number) and y (一个 Number) and returns 一个整数 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 (一个 Number) and radix (2 到 36 之间的整数) and returns 一个字符串. 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 整除,且最低位未必唯一。
  6. 如果 radix ≠ 10 或 n 在 -5 到 21 的区间内:
    1. 如果 nk
      1. 返回拼接字符串:
        • 用基数 radix 表示 sk 位数字
        • n - k 个 0x0030(数字零)码位
    2. 否则如 n > 0:
      1. 返回拼接字符串:
        • 用基数 radix 表示 s 的最高 n 位数字
        • 0x002E(英文句点)
        • 剩余 k - n 位数字
    3. 否则:
      1. 断言:n ≤ 0。
      2. 返回拼接字符串:
        • 0x0030(数字零)码位
        • 0x002E(英文句点)
        • -n 个 0x0030(数字零)码位
        • 用基数 radix 表示 sk 位数字
  7. 注意:此时输入会用科学 E 记数法表示,如 1.2e+3
  8. 断言:radix 为 10。
  9. 如果 n < 0:
    1. exponentSign 为 0x002D(减号)。
  10. 否则:
    1. exponentSign 为 0x002B(加号)。
  11. 如果 k = 1:
    1. 返回拼接字符串:
      • s 的单一数字码位
      • 0x0065(小写字母 e)
      • exponentSign
      • abs(n - 1) 的十进制表示码位
  12. 返回拼接字符串:
    • s 十进制表示的最高位数字码位
    • 0x002E(英文句点)
    • s 十进制表示的剩余 k - 1 位码位
    • 0x0065(小写字母 e)
    • exponentSign
    • abs(n - 1) 的十进制表示码位
Note 1

以下观察可为实现提供参考,但不是标准的规范要求:

  • -0𝔽 外,任意 Number 值 x 都满足 ToNumber(ToString(x)) === x。
  • 步骤 5s 的最低位不总是唯一确定。
Note 2

对于提供比上述规则更精确转换的实现,建议参考如下步骤 5 的替代版本:

  1. nks 为整数,满足 k ≥ 1,radixk - 1s < radixk𝔽(s × radixn - k) 为 x,且 k 尽可能小。如果有多个 s,选择 s × radixn - k 最接近 (x) 的那个;如有两个结果,选偶数的那个。注意 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). 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 ( x )

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

  1. 如果 x = 0,返回 0
  2. 返回 -x

6.1.6.2.2 BigInt::bitwiseNOT ( x )

The abstract operation BigInt::bitwiseNOT takes argument x (一个 BigInt) and returns 一个 BigInt. It performs the following steps when called:

  1. 返回 -x - 1

6.1.6.2.3 BigInt::exponentiate ( base, exponent )

The abstract operation BigInt::exponentiate takes arguments base (一个 BigInt) and exponent (一个 BigInt) and returns 正常返回一个 BigInt 或抛出异常. 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 (一个 BigInt) and y (一个 BigInt) and returns 一个 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 (一个 BigInt) and y (一个 BigInt) and returns 正常返回一个 BigInt 或抛出异常. 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 ( n, d )

The abstract operation BigInt::remainder takes arguments n (一个 BigInt) and d (一个 BigInt) and returns 正常返回一个 BigInt 或抛出异常. It performs the following steps when called:

  1. 如果 d = 0,抛出 RangeError 异常。
  2. 如果 n = 0,返回 0
  3. quotient(n) / (d)。
  4. q(truncate(quotient))。
  5. 返回 n - (d × q)。
Note
结果的符号与被除数一致。

6.1.6.2.7 BigInt::add ( x, y )

The abstract operation BigInt::add takes arguments x (一个 BigInt) and y (一个 BigInt) and returns 一个 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 (一个 BigInt) and y (一个 BigInt) and returns 一个 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 (一个 BigInt) and y (一个 BigInt) and returns 一个 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 (一个 BigInt) and y (一个 BigInt) and returns 一个 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 (一个 BigInt) and y (一个 BigInt) and returns 抛出异常. 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 (一个 BigInt) and y (一个 BigInt) and returns Boolean. It performs the following steps when called:

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

6.1.6.2.13 BigInt::equal ( x, y )

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

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

6.1.6.2.14 BinaryAnd ( x, y )

The abstract operation BinaryAnd takes arguments x (0 或 1) and y (0 或 1) and returns 0 或 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 或 1) and y (0 或 1) and returns 0 或 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 或 1) and y (0 或 1) and returns 0 或 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 (&, ^, 或 |), x (一个 BigInt), and y (一个 BigInt) and returns 一个 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 模 2。
    2. yDigity 模 2。
    3. 如果 op&
      1. resultresult + 2shift × BinaryAnd(xDigit, yDigit)。
    4. 否则如果 op|
      1. resultresult + 2shift × BinaryOr(xDigit, yDigit)。
    5. 否则,
      1. 断言:op^
      2. resultresult + 2shift × BinaryXor(xDigit, yDigit)。
    6. shiftshift + 1。
    7. x 为 (x - xDigit) / 2。
    8. y 为 (y - yDigit) / 2。
  6. 如果 op&
    1. tmpBinaryAnd(x 模 2, y 模 2)。
  7. 否则如果 op|
    1. tmpBinaryOr(x 模 2, y 模 2)。
  8. 否则,
    1. 断言:op^
    2. tmpBinaryXor(x 模 2, y 模 2)。
  9. 如果 tmp ≠ 0,
    1. resultresult - 2shift
    2. 注意:此操作会扩展符号位。
  10. 返回 resultBigInt 值

6.1.6.2.18 BigInt::bitwiseAND ( x, y )

The abstract operation BigInt::bitwiseAND takes arguments x (一个 BigInt) and y (一个 BigInt) and returns 一个 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 (一个 BigInt) and y (一个 BigInt) and returns 一个 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 (一个 BigInt) and y (一个 BigInt) and returns 一个 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 (一个 BigInt) and radix (2 到 36 之间的整数) and returns 一个字符串. It performs the following steps when called:

  1. 如果 x < 0,返回 "-"BigInt::toString(-x, radix) 的拼接字符串。
  2. 返回用基数 radix 表示 x 的字符串值。

6.1.7 对象类型

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

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

对象的属性通过属性键唯一标识。属性键可以是字符串或符号。所有字符串和符号,包括空字符串,都是有效的属性键属性名属性键为字符串的情况。

整数索引属性名 n,满足 CanonicalNumericIndexString(n) 返回一个在 +0𝔽𝔽(253 - 1) 的闭区间内的整数 Number。数组索引整数索引 n,且 CanonicalNumericIndexString(n) 返回一个在 +0𝔽𝔽(232 - 2) 的闭区间内的整数 Number。

Note

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

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

所有对象在逻辑上都是属性的集合,但对象有多种形式,不同形式在访问和操作属性时语义有所区别。参见 6.1.7.2 以了解对象的多种形式定义。

此外,某些对象可调用,被称为函数或函数对象,详见下文。所有 ECMAScript 中的函数都是 Object 类型成员。

6.1.7.1 属性特性

本规范使用属性(attributes)来定义和解释对象属性的状态,详见 Table 3。除非明确说明,每个属性的初始值为其默认值。

Table 3: 对象属性的特性
特性名称 适用属性类型 值域 默认值 描述
[[Value]] 数据属性 一个 ECMAScript 语言值 undefined 通过 get 访问属性时获得的值。
[[Writable]] 数据属性 布尔值 false 如果为 false,则 ECMAScript 代码通过 [[Set]] 尝试改变属性的 [[Value]] 特性不会成功。
[[Get]] 访问器属性 对象或 undefined undefined 如果值是对象,则必须为函数对象。每次对属性进行 get 访问时,调用该函数的 [[Call]] 内部方法(参见 Table 5),参数列表为空,以获取属性值。
[[Set]] 访问器属性 对象或 undefined undefined 如果值是对象,则必须为函数对象。每次对属性进行 set 访问时,调用该函数的 [[Call]] 内部方法(参见 Table 5),参数列表只包含要赋值的值。属性的 [[Set]] 内部方法的效果可以影响后续 [[Get]] 的返回值,但不是必须的。
[[Enumerable]] 数据属性访问器属性 布尔值 false 如果为 true,属性会被 for-in 枚举(参见 14.7.5);否则,该属性被称为不可枚举
[[Configurable]] 数据属性访问器属性 布尔值 false 如果为 false,尝试删除属性、将其从数据属性变为访问器属性或反之,以及对其特性的任何修改(除了替换已有 [[Value]] 或设置 [[Writable]]false)都不会成功。

6.1.7.2 对象的内部方法与内部槽

ECMAScript 中对象的实际语义通过称为内部方法的算法来定义。每个 ECMAScript 引擎中的对象都关联一组内部方法,定义其运行时行为。这些内部方法不是 ECMAScript 语言的一部分,仅供规范说明之用。但 ECMAScript 的每个对象都必须符合其关联的内部方法的行为,具体实现方式由实现决定。

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

内部槽对应于与对象、Symbol 或私有名称关联的内部状态,被 ECMAScript 规范的各种算法使用。内部槽不是对象属性,也不会被继承。根据具体内部槽的规定,这些状态可以是任意 ECMAScript 类型值或特定 ECMAScript 规范类型值。除非另有说明,内部槽在创建对象、Symbol 或私有名称时分配,不能动态添加。除非另有说明,内部槽的初始值是 undefined。本规范中的各种算法会创建具有内部槽的值。但 ECMAScript 语言无法直接操作内部槽。

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

规范中用双中括号 [[ ]] 标识内部方法和内部槽。

Table 4 总结了本规范用于所有 ECMAScript 创建或操作的对象所适用的基本内部方法。每个对象必须实现所有这些基本内部方法的算法,但并不一定所有对象都用相同的算法。

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

  • 对于 Table 4 列出的内部方法,对象采用 10.1 中定义的方法。
  • 如果对象有 [[Call]] 内部方法,则采用 10.2.110.3.1 中定义的方法。
  • 如果对象有 [[Construct]] 内部方法,则采用 10.2.210.3.2 中定义的方法。

特殊对象是不满足普通对象条件的对象。

本规范通过对象的内部方法区分不同类型的特殊对象。如果一个对象在行为上等同于某种特殊对象(如数组特殊对象或绑定函数特殊对象),但没有实现该类型指定的所有内部方法,则不被视为该类型的特殊对象

Table 4和类似表格的“签名”列描述了每个内部方法的调用模式。调用模式总包括一个括号包裹的参数名列表。如果参数名与 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 的属性描述符,若无则返回 undefined
[[DefineOwnProperty]] (propertyKey, PropertyDescriptor) Boolean 创建或更改自身属性(键为 propertyKey),使其状态与 PropertyDescriptor 描述一致。成功时返回 true,否则返回 false
[[HasProperty]] (propertyKey) 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]] ( ) 属性键列表 返回对象所有自身属性键的列表。

Table 5 总结了函数对象支持的附加基本内部方法。函数对象是支持 [[Call]] 内部方法的对象。构造函数是支持 [[Construct]] 内部方法的对象。每个支持 [[Construct]] 的对象都必须支持 [[Call]],即每个构造函数也是函数对象。因此构造函数也可称为构造函数对象

Table 5: 函数对象的附加基本内部方法
内部方法 签名 描述
[[Call]] (any, any 列表) any 执行与此对象关联的代码。通过函数调用表达式调用。方法参数为 this 值及调用表达式传递的参数列表。实现此方法的对象为可调用对象。
[[Construct]] (any 列表, Object) Object 创建对象。通过 new 操作符或 super 调用。第一个参数为构造器调用或 super 调用的参数列表,第二个参数为最初应用 new 操作符的对象。实现此方法的对象为构造函数函数对象不一定是构造函数,非构造函数对象没有 [[Construct]] 方法。

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

6.1.7.3 基本内部方法的不变量

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

任何实现提供的特殊对象也必须为这些对象保持这些不变量。违反这些不变量可能导致 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 类型的 Completion Record

[[GetPrototypeOf]] ( )

  • 正常返回类型为 Object 或 Null。
  • 如果目标为不可扩展,且 [[GetPrototypeOf]] 返回值 V,则未来对 [[GetPrototypeOf]] 的调用都应返回与 V SameValue 的值。
Note 2

对象的原型链应有限(即从任意对象递归调用 [[GetPrototypeOf]] 最终应到达 null)。但如果原型链中包含未采用普通对象定义的特殊对象,则无法作为对象级不变量强制此要求。出现环形原型链时,访问对象属性可能导致无限循环。

[[SetPrototypeOf]] ( V )

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

[[IsExtensible]] ( )

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

[[PreventExtensions]] ( )

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

[[GetOwnProperty]] ( P )

  • 正常返回类型为 Property Descriptor 或 Undefined。
  • 如果返回值为 Property Descriptor,必须是完整的 Property Descriptor
  • 如果 P 被描述为不可配置、不可写的自身数据属性,则未来对 [[GetOwnProperty]] ( P ) 的所有调用都必须返回 [[Value]]P[[Value]] 属性 SameValueProperty Descriptor
  • 如果 P[[Writable]][[Value]] 外的属性可能随时间变化,或属性可能被删除,则 P[[Configurable]] 属性必须为 true
  • 如果 [[Writable]] 属性可能从 false 变为 true,则 [[Configurable]] 属性必须为 true
  • 如果目标为不可扩展且 P 不存在,则未来对目标的所有 [[GetOwnProperty]] (P) 调用都必须描述 P 为不存在(即返回 undefined)。
Note 3

由第三条不变量可知,如果某属性被描述为数据属性且可能随时间返回不同值,则无论是否暴露机制修改值,只要有可能,[[Writable]][[Configurable]] 属性至少有一个必须为 true

[[DefineOwnProperty]] ( P, Desc )

  • 正常返回类型为 Boolean。
  • 除非满足以下之一,否则 [[DefineOwnProperty]] 必须返回 false,如果 P 已被观察为目标的不可配置自身属性:
    1. P 是可写数据属性。不可配置且可写的数据属性可以变为不可配置且不可写的数据属性
    2. Desc 的所有属性与 P 的属性 SameValue
  • 如果目标为不可扩展且 P 是不存在的自身属性,则 [[DefineOwnProperty]] (P, Desc) 必须返回 false。即不可扩展对象不能添加新属性。

[[HasProperty]] ( P )

  • 正常返回类型为 Boolean。
  • 如果 P 已被观察为目标的不可配置自身数据或访问器属性,则 [[HasProperty]] 必须返回 true

[[Get]] ( P, Receiver )

  • 正常返回类型为任意 ECMAScript 语言类型
  • 如果 P 已被观察为目标的不可配置、不可写自身数据属性且值为 V,则 [[Get]] 必须返回与 V SameValue 的值。
  • 如果 P 已被观察为目标的不可配置自身访问器属性[[Get]] 属性为 undefined,则 [[Get]] 操作必须返回 undefined

[[Set]] ( P, V, Receiver )

  • 正常返回类型为 Boolean。
  • 如果 P 已被观察为目标的不可配置、不可写自身数据属性,则除非 VP[[Value]] 属性 SameValue[[Set]] 必须返回 false
  • 如果 P 已被观察为目标的不可配置自身访问器属性[[Set]] 属性为 undefined,则 [[Set]] 操作必须返回 false

[[Delete]] ( P )

  • 正常返回类型为 Boolean。
  • 如果 P 已被观察为目标的不可配置自身数据或访问器属性,则 [[Delete]] 必须返回 false

[[OwnPropertyKeys]] ( )

  • 正常返回类型为 List
  • 返回的 List 不能有重复项。
  • 返回的 List 的每个元素必须是属性键
  • 返回的 List 至少含有所有已观察到的不可配置自身属性的键。
  • 如果目标为不可扩展,则返回的 List 只能包含所有可通过 [[GetOwnProperty]] 观察到的自身属性键

[[Call]] ( )

[[Construct]] ( )

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

6.1.7.4 知名内置对象

知名内置对象是本规范的算法显式引用的内置对象,通常具有特定于“域”(realm)的身份。除非另有说明,每个内置对象实际对应一组类似对象,每个域各一个。

在本规范中,%name% 表示当前域关联的对应名称的内置对象。%name.a.b% 表示在执行任何 ECMAScript 代码之前,访问内置对象 %name% 的属性 "a",再访问该属性的 "b" 属性。当前域和其内置对象的确定见 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% 数组迭代器对象的原型(参见 23.1.5
%AsyncFromSyncIteratorPrototype% Async-from-Sync 迭代器对象的原型(参见 27.1.6
%AsyncFunction% async 函数对象构造函数(参见 27.7.1
%AsyncGeneratorFunction% async 生成器函数对象构造函数(参见 27.4.1
%AsyncGeneratorPrototype% async 生成器对象的原型(参见 27.6
%AsyncIteratorPrototype% 所有标准内置 async 迭代器对象的间接继承对象
%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
%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 迭代器对象的原型(参见 14.7.5.10
%Function% Function Function 构造函数(参见 20.2.1
%GeneratorFunction% 生成器函数对象构造函数(参见 27.3.1
%GeneratorPrototype% 生成器对象的原型(参见 27.5
%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 迭代器对象的原型(参见 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.2.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% 正则表达式字符串迭代器对象的原型(参见 22.2.9
%Set% Set Set 构造函数(参见 24.2.2
%SetIteratorPrototype% Set 迭代器对象的原型(参见 24.2.6
%SharedArrayBuffer% SharedArrayBuffer SharedArrayBuffer 构造函数(参见 25.2.3
%String% String String 构造函数(参见 22.1.1
%StringIteratorPrototype% 字符串迭代器对象的原型(参见 22.1.5
%Symbol% Symbol Symbol 构造函数(参见 20.4.1
%SyntaxError% SyntaxError SyntaxError 构造函数(参见 20.5.5.4
%ThrowTypeError% 一个函数对象,总是抛出新的 %TypeError% 实例
%TypedArray% 所有类型化数组构造函数的超类(参见 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.1.1
Note

更多条目见 Table 100

6.2 ECMAScript 规范类型

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

6.2.1 枚举规范类型

枚举是规范内部使用的值,不能被 ECMAScript 代码直接观察。枚举用 无衬线体 表示。例如,Completion Record[[Type]] 字段会取 normalreturnthrow 等值。枚举除了名称外没有其他特性。枚举的名称仅用于与其他枚举区分,并不暗示其在上下文中的用途或意义。

6.2.2 List 和 Record 规范类型

List 类型用于解释参数列表(参见 13.3.8)在 new 表达式、函数调用以及需要简单有序值列表的其他算法中的求值。List 类型的值就是包含各个值的有序元素序列,序列长度可任意。List 的元素可用 0 起始的索引随机访问。为方便记号,可用类似数组的语法访问 List 元素。例如,arguments[2] 表示 List arguments 的第 3 个元素。

当算法遍历 List 元素但未指定顺序时,使用 List 元素的原有顺序。

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

在本规范中,“AB... 的列表拼接”(每个参数都是可能为空的 List)表示一个新 List,其元素是各参数元素(按顺序)拼接而成。

对于字符串 List,“按字典序码位顺序排序”意指按较短字符串长度以内各码位的数值排序,如相等则短字符串排前,详见抽象操作 IsLessThan

Record 类型用于规范算法中的数据聚合。Record 类型值由一个或多个具名字段组成,每个字段的值为 ECMAScript 语言值或规范值。字段名总用双括号包裹,例如 [[Value]]

在规范中,为方便记号,可用类似对象字面量的语法表达 Record 值。例如,{ [[Field1]]: 42, [[Field2]]: false, [[Field3]]: empty } 表示一个包含三个字段的 Record 值,每个字段初始化为特定值。字段名顺序无关紧要,未列出的字段视为不存在。

在规范文本和算法中,可用点号表示法引用 Record 的某个字段。例如,若 R 为上文的 Record,则 R.[[Field2]] 表示“R 的 [[Field2]] 字段”。

常用字段组合的 Record 可以命名,并作为字面量前缀,以标识描述的聚合类型。例如:PropertyDescriptor { [[Value]]: 42, [[Writable]]: false, [[Configurable]]: true }。

6.2.3 Set 和 Relation 规范类型

Set 类型用于说明内存模型中无序元素集合。它不同于 ECMAScript 集合类型 Set。为区分,规范中 ECMAScript 集合类型始终称为“Set 对象”。Set 类型值是元素集合,每个元素只出现一次。元素可加入或移除集合,集合之间可以并集、交集或相减。

Relation 类型用于说明集合上的约束。Relation 类型值是其值域上的有序对集合。例如,事件上的 Relation 是事件有序对的集合。若 Relation R,值域中的 ab,则 a 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

    • a 等于 ba R bb R a,且
    • 不存在 a R a,且
    • a R bb R c,则 a R c
Note 2

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

6.2.4 Completion Record 规范类型

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

Completion Record 包含 Table 7 定义的字段。

Table 7: Completion Record 字段
字段名 含义
[[Type]] normalbreakcontinuereturnthrow 发生的完成类型。
[[Value]] Completion Record 外的任何值 产生的值。
[[Target]] 字符串或 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]] 字段为该类型值的正常完成。

规范中定义的可调用对象只返回正常完成或 throw 完成。返回其他类型的 Completion Record 属于编辑错误。

实现自定义的可调用对象也必须只返回正常完成或 throw 完成。

6.2.4.1 NormalCompletion ( value )

The abstract operation NormalCompletion takes argument value (除 Completion Record 外的任何值) and returns 正常完成. 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 (一个 ECMAScript 语言值) and returns throw 完成. 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 (一个 ECMAScript 语言值) and returns return 完成. 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 (一个 Completion Record) and value (除 Completion Record 外的任何值) and returns 一个 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,则总为字符串。否则,可能为除字符串和符号外的 ECMAScript 语言值,直到执行 ToPropertyKey
[[Strict]] 布尔值 Reference Record 来源于严格模式代码,则为 true,否则为 false
[[ThisValue]] 一个 ECMAScript 语言值empty 若非 empty,则代表用 super 关键字表达的属性绑定,称为 Super Reference Record,其 [[Base]] 不会是 Environment Record。此时 [[ThisValue]] 字段保存创建 Reference Record 时的 this 值。

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

6.2.5.1 IsPropertyReference ( V )

The abstract operation IsPropertyReference takes argument V (一个 Reference Record) and returns 布尔值. It performs the following steps when called:

  1. V.[[Base]]unresolvable,返回 false
  2. V.[[Base]]Environment Record,返回 false;否则返回 true

6.2.5.2 IsUnresolvableReference ( V )

The abstract operation IsUnresolvableReference takes argument V (一个 Reference Record) and returns 布尔值. It performs the following steps when called:

  1. V.[[Base]]unresolvable,返回 true;否则返回 false

6.2.5.3 IsSuperReference ( V )

The abstract operation IsSuperReference takes argument V (一个 Reference Record) and returns 布尔值. It performs the following steps when called:

  1. V.[[ThisValue]]empty,返回 true;否则返回 false

6.2.5.4 IsPrivateReference ( V )

The abstract operation IsPrivateReference takes argument V (一个 Reference Record) and returns 布尔值. It performs the following steps when called:

  1. V.[[ReferencedName]]Private Name,返回 true;否则返回 false

6.2.5.5 GetValue ( V )

The abstract operation GetValue takes argument V (一个 Reference RecordECMAScript 语言值) and returns 返回包含 ECMAScript 语言值正常完成异常完成. It performs the following steps when called:

  1. V 不是 Reference Record,返回 V
  2. IsUnresolvableReference(V) 为 true,抛出 ReferenceError 异常。
  3. IsPropertyReference(V) 为 true
    1. baseObj 为 ? ToObject(V.[[Base]])。
    2. IsPrivateReference(V) 为 true
      1. 返回 ? PrivateGet(baseObj, V.[[ReferencedName]])。
    3. V.[[ReferencedName]] 不是属性键
      1. V.[[ReferencedName]] 为 ? ToPropertyKey(V.[[ReferencedName]])。
    4. 返回 ? baseObj.[[Get]](V.[[ReferencedName]], GetThisValue(V))。
  4. 否则,
    1. baseV.[[Base]]
    2. 断言:baseEnvironment Record
    3. 返回 ? base.GetBindingValue(V.[[ReferencedName]], V.[[Strict]])(参见 9.1)。
Note

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

6.2.5.6 PutValue ( V, W )

The abstract operation PutValue takes arguments V (一个 Reference RecordECMAScript 语言值) and W (一个 ECMAScript 语言值) and returns 返回包含 unused正常完成异常完成. It performs the following steps when called:

  1. V 不是 Reference Record,抛出 ReferenceError 异常。
  2. IsUnresolvableReference(V) 为 true
    1. V.[[Strict]]true,抛出 ReferenceError 异常。
    2. globalObjGetGlobalObject()。
    3. 执行 ? Set(globalObj, V.[[ReferencedName]], W, false)。
    4. 返回 unused
  3. IsPropertyReference(V) 为 true
    1. baseObj 为 ? ToObject(V.[[Base]])。
    2. IsPrivateReference(V) 为 true
      1. 返回 ? PrivateSet(baseObj, V.[[ReferencedName]], W)。
    3. V.[[ReferencedName]] 不是属性键
      1. V.[[ReferencedName]] 为 ? ToPropertyKey(V.[[ReferencedName]])。
    4. succeeded 为 ? baseObj.[[Set]](V.[[ReferencedName]], W, GetThisValue(V))。
    5. succeededfalseV.[[Strict]]true,抛出 TypeError 异常。
    6. 返回 unused
  4. 否则,
    1. baseV.[[Base]]
    2. 断言:baseEnvironment Record
    3. 返回 ? base.SetMutableBinding(V.[[ReferencedName]], W, V.[[Strict]])(参见 9.1)。
Note

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

6.2.5.7 GetThisValue ( V )

The abstract operation GetThisValue takes argument V (一个 Reference Record) and returns 一个 ECMAScript 语言值. It performs the following steps when called:

  1. 断言:IsPropertyReference(V) 为 true
  2. IsSuperReference(V) 为 true,返回 V.[[ThisValue]];否则返回 V.[[Base]]

6.2.5.8 InitializeReferencedBinding ( V, W )

The abstract operation InitializeReferencedBinding takes arguments V (一个 Reference Record) and W (一个 ECMAScript 语言值) and returns 返回包含 unused正常完成异常完成. It performs the following steps when called:

  1. 断言:IsUnresolvableReference(V) 为 false
  2. baseV.[[Base]]
  3. 断言:baseEnvironment Record
  4. 返回 ? base.InitializeBinding(V.[[ReferencedName]], W)。

6.2.5.9 MakePrivateReference ( baseValue, privateIdentifier )

The abstract operation MakePrivateReference takes arguments baseValue (一个 ECMAScript 语言值) and privateIdentifier (字符串) and returns 一个 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 类型用于解释对象属性特性的操作及具现。Property Descriptor 是一个包含零个或多个字段的 Record,每个字段名为特性名,值为 6.1.7.1 所定义的特性值。本规范用 “PropertyDescriptor” 作为字面量描述 Property Descriptor Record 的标签名称。

Property Descriptor 值可根据某些字段的存在或用途进一步分为数据 Property Descriptor 和访问器 Property Descriptor。包含 [[Value]][[Writable]] 字段的为数据 Property Descriptor;包含 [[Get]][[Set]] 字段的为访问器 Property Descriptor。任意 Property Descriptor 都可包含 [[Enumerable]][[Configurable]] 字段。Property Descriptor 值不能同时为数据和访问器 Property Descriptor,但可以两者都不是(此时为通用 Property Descriptor)。完全填充的 Property Descriptor指为访问器 Property Descriptor 或数据 Property Descriptor 且已定义所有对应字段(见 Table 3)。

本规范用以下抽象操作处理 Property Descriptor 值:

6.2.6.1 IsAccessorDescriptor ( Desc )

The abstract operation IsAccessorDescriptor takes argument Desc (一个 Property Descriptor) and returns 布尔值. It performs the following steps when called:

  1. Desc[[Get]] 字段,返回 true
  2. Desc[[Set]] 字段,返回 true
  3. 返回 false

6.2.6.2 IsDataDescriptor ( Desc )

The abstract operation IsDataDescriptor takes argument Desc (一个 Property Descriptor) and returns 布尔值. It performs the following steps when called:

  1. Desc[[Value]] 字段,返回 true
  2. Desc[[Writable]] 字段,返回 true
  3. 返回 false

6.2.6.3 IsGenericDescriptor ( Desc )

The abstract operation IsGenericDescriptor takes argument Desc (一个 Property Descriptor) and returns 布尔值. It performs the following steps when called:

  1. IsAccessorDescriptor(Desc) 为 true,返回 false
  2. IsDataDescriptor(Desc) 为 true,返回 false
  3. 返回 true

6.2.6.4 FromPropertyDescriptor ( Desc )

The abstract operation FromPropertyDescriptor takes argument Desc (一个 Property Descriptorundefined) and returns 一个对象或 undefined. It performs the following steps when called:

  1. Descundefined,返回 undefined
  2. objOrdinaryObjectCreate(%Object.prototype%)。
  3. 断言:obj 是可扩展的普通对象且无自身属性。
  4. Desc[[Value]] 字段,
    1. 执行 ! CreateDataPropertyOrThrow(obj, "value", Desc.[[Value]])。
  5. Desc[[Writable]] 字段,
    1. 执行 ! CreateDataPropertyOrThrow(obj, "writable", Desc.[[Writable]])。
  6. Desc[[Get]] 字段,
    1. 执行 ! CreateDataPropertyOrThrow(obj, "get", Desc.[[Get]])。
  7. Desc[[Set]] 字段,
    1. 执行 ! CreateDataPropertyOrThrow(obj, "set", Desc.[[Set]])。
  8. Desc[[Enumerable]] 字段,
    1. 执行 ! CreateDataPropertyOrThrow(obj, "enumerable", Desc.[[Enumerable]])。
  9. Desc[[Configurable]] 字段,
    1. 执行 ! CreateDataPropertyOrThrow(obj, "configurable", Desc.[[Configurable]])。
  10. 返回 obj

6.2.6.5 ToPropertyDescriptor ( Obj )

The abstract operation ToPropertyDescriptor takes argument Obj (一个 ECMAScript 语言值) and returns 返回包含 Property Descriptor正常完成异常完成. It performs the following steps when called:

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

6.2.6.6 CompletePropertyDescriptor ( Desc )

The abstract operation CompletePropertyDescriptor takes argument Desc (一个 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(Desc) 为 trueIsDataDescriptor(Desc) 为 true
    1. Desc[[Value]] 字段,设置 Desc.[[Value]]like.[[Value]]
    2. Desc[[Writable]] 字段,设置 Desc.[[Writable]]like.[[Writable]]
  3. 否则,
    1. Desc[[Get]] 字段,设置 Desc.[[Get]]like.[[Get]]
    2. Desc[[Set]] 字段,设置 Desc.[[Set]]like.[[Set]]
  4. Desc[[Enumerable]] 字段,设置 Desc.[[Enumerable]]like.[[Enumerable]]
  5. Desc[[Configurable]] 字段,设置 Desc.[[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 的算法步骤,用 “capture” 和别名列表描述需捕获的值。创建时,按别名捕获当时关联的值。指定 Abstract Closure 被调用时的算法步骤时,每个捕获值都用其别名引用。

若 Abstract Closure 返回 Completion Record,则必须是正常完成throw 完成

Abstract Closure 通常作为其他算法的一部分内联创建,示例如下:

  1. addend 为 41。
  2. closure 为新建 Abstract Closure,参数 (x),捕获 addend,调用时执行以下步骤:
    1. 返回 x + addend
  3. valclosure(1)。
  4. 断言:val 为 42。

6.2.9 数据块

Data Block 规范类型用于描述一段独立且可变的字节(8 位)数值序列。字节值是 0 到 255 的整数。Data Block 值创建时拥有固定数量字节,每个初始值为 0。

在规范中,为方便记号,可用类似数组的语法访问 Data Block 的各字节。该记号将 Data Block 视为 0 起始整数索引的字节序列。例如,若 db 为 5 字节 Data Block,则 db[2] 用于访问第 3 个字节。

可被多个 agent 并发引用的驻留于内存的数据块称为 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 )

The abstract operation CreateByteDataBlock takes argument size (非负整数) and returns 返回包含 Data Block正常完成异常完成. It performs the following steps when called:

  1. size > 253 - 1,抛出 RangeError 异常。
  2. db 为由 size 字节组成的新 Data Block 值。若无法创建该 Data Block,抛出 RangeError 异常。
  3. db 的所有字节设为 0。
  4. 返回 db

6.2.9.2 CreateSharedByteDataBlock ( size )

The abstract operation CreateSharedByteDataBlock takes argument size (非负整数) and returns 返回包含 Shared Data Block正常完成异常完成. It performs the following steps when called:

  1. db 为由 size 字节组成的新 Shared Data Block 值。若无法创建该 Shared Data Block,抛出 RangeError 异常。
  2. execution 为当前 agent 的 Agent Record[[CandidateExecution]] 字段。
  3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
  4. zero 为 « 0 »。
  5. db 的每个索引 i
    1. WriteSharedMemory { [[Order]]: init, [[NoTear]]: true, [[Block]]: db, [[ByteIndex]]: i, [[ElementSize]]: 1, [[Payload]]: zero } 添加到 eventsRecord.[[EventList]]
  6. 返回 db

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

The abstract operation CopyDataBlockBytes takes arguments toBlock (Data BlockShared Data Block), toIndex (非负整数), fromBlock (Data BlockShared Data Block), fromIndex (非负整数), and count (非负整数) 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. execution 为当前 agent 的 Agent Record[[CandidateExecution]] 字段。
      2. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
      3. bytes 为仅有一个由非确定性选择的字节值List
      4. 注:在实现中,bytes 是底层硬件非原子读指令的结果。非确定性由内存模型语义规定,以描述弱一致性硬件的可观察行为。
      5. readEventReadSharedMemory { [[Order]]: unordered, [[NoTear]]: true, [[Block]]: fromBlock, [[ByteIndex]]: fromIndex, [[ElementSize]]: 1 }。
      6. readEvent 添加到 eventsRecord.[[EventList]]
      7. Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: bytes } 添加到 execution.[[ChosenValues]]
      8. toBlockShared Data Block
        1. WriteSharedMemory { [[Order]]: unordered, [[NoTear]]: true, [[Block]]: toBlock, [[ByteIndex]]: toIndex, [[ElementSize]]: 1, [[Payload]]: bytes } 添加到 eventsRecord.[[EventList]]
      9. 否则,
        1. 设置 toBlock[toIndex] 为 bytes[0]。
    2. 否则,
      1. 断言:toBlock 不是 Shared Data Block
      2. 设置 toBlock[toIndex] 为 fromBlock[fromIndex]。
    3. 设置 toIndextoIndex + 1。
    4. 设置 fromIndexfromIndex + 1。
    5. 设置 countcount - 1。
  7. 返回 unused

6.2.10 PrivateElement 规范类型

PrivateElement 类型是用于规范私有类字段、方法和访问器的 Record。虽然 PrivateElement 不用 Property Descriptor,但私有字段的行为类似于不可配置、不可枚举、可写的数据属性,私有方法类似于不可配置、不可枚举、不可写的数据属性,私有访问器类似于不可配置、不可枚举访问器属性

PrivateElement 类型的值是包含 Table 9 定义字段的 Record。此类值称为 PrivateElements

Table 9: PrivateElement 字段
字段名 存在时 [[Kind]] 字段的值 含义
[[Key]] 所有 Private Name 字段、方法或访问器的名称。
[[Kind]] 所有 fieldmethodaccessor 元素类型。
[[Value]] fieldmethod 一个 ECMAScript 语言值 字段的值。
[[Get]] accessor 函数对象undefined 私有访问器的 getter。
[[Set]] accessor 函数对象undefined 私有访问器的 setter。

6.2.11 ClassFieldDefinition Record 规范类型

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

ClassFieldDefinition 类型的值是包含 Table 10 定义字段的 Record。此类值称为 ClassFieldDefinition Records

Table 10: ClassFieldDefinition Record 字段
字段名 含义
[[Name]] Private Name、字符串或符号 字段的名称。
[[Initializer]] ECMAScript 函数对象empty 字段的初始化器(如有)。

6.2.12 Private Name

Private Name 规范类型用于描述全局唯一值(即使与其他 Private Name 外观一致也不同),用于表示私有类元素(字段、方法或访问器)的键。每个 Private Name 有不可变的 [[Description]] 内部槽,为字符串。Private Name 可通过 PrivateFieldAddPrivateMethodOrAccessorAdd 安装到任意 ECMAScript 对象上,然后可用 PrivateGetPrivateSet 读取或写入。

6.2.13 ClassStaticBlockDefinition Record 规范类型

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

ClassStaticBlockDefinition Record 包含 Table 11 列出的字段。

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