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

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

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

短语“strinclusiveStartexclusiveEnd子字符串”(其中 str 是 String 值或码元 序列,inclusiveStartexclusiveEnd整数)表示这样一个 String 值:它由 str 中从索引 inclusiveStart 开始,到索引 exclusiveEnd 之前立即结束的连续码元构成(当 inclusiveStart = exclusiveEnd 时,它就是空 String)。如果省略 “to” 后缀,则使用 str 的长度作为 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 (一个 String,), searchValue (一个 String,), and fromIndex (一个非负整数,) and returns 一个非负整数not-found. It performs the following steps when called:

  1. lenstring 的长度。
  2. searchValue 是空 String 且 fromIndexlen,返回 fromIndex
  3. searchLensearchValue 的长度。
  4. 对每个满足 fromIndexilen - searchLen整数 i,按升序执行
    1. candidatestringii + searchLen子字符串
    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 (一个 String,), searchValue (一个 String,), and fromIndex (一个非负整数,) and returns 一个非负整数not-found. It performs the following steps when called:

  1. lenstring 的长度。
  2. searchLensearchValue 的长度。
  3. 断言:fromIndex + searchLenlen
  4. 对每个满足 0 ≤ ifromIndex整数 i,按降序执行
    1. candidatestringii + searchLen子字符串
    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 众所周知的 Symbol

众所周知的 symbol 是由本规范算法显式引用的内建 Symbol 值。 它们通常用作属性的键,而这些属性的值充当规范算法的扩展点。除非另有 说明,众所周知的 symbol 值由所有 realm 共享(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
规范名称 [[Description]] 值与用途
%Symbol.asyncIterator% "Symbol.asyncIterator" 一个方法,返回对象的默认异步迭代器。由 for-await-of 语句的语义调用。
%Symbol.hasInstance% "Symbol.hasInstance" 一个方法,用于确定某个构造器对象是否将某对象识别为该构造器 的一个实例。由 instanceof 运算符的语义调用。
%Symbol.isConcatSpreadable% "Symbol.isConcatSpreadable" 一个 Boolean 值属性,若为 true,则表示对象应当被 Array.prototype.concat 展开为其数组元素。
%Symbol.iterator% "Symbol.iterator" 一个方法,返回对象的默认迭代器。由 for-of 语句的语义 调用。
%Symbol.match% "Symbol.match" 一个正则表达式方法,用于将正则表达式与字符串进行匹配。 由 String.prototype.match 方法调用。
%Symbol.matchAll% "Symbol.matchAll" 一个正则表达式方法,返回一个迭代器,该迭代器会产出正则表达式 对字符串匹配得到的各个结果。由 String.prototype.matchAll 方法调用。
%Symbol.replace% "Symbol.replace" 一个正则表达式方法,用于替换字符串中匹配到的子字符串。 由 String.prototype.replace 方法调用。
%Symbol.search% "Symbol.search" 一个正则表达式方法,返回字符串中匹配该正则表达式的位置索引。 由 String.prototype.search 方法调用。
%Symbol.species% "Symbol.species" 一个函数值属性,它是用于创建派生对象的构造器函数。
%Symbol.split% "Symbol.split" 一个正则表达式方法,用于在字符串中按匹配该正则表达式的索引 进行分割。由 String.prototype.split 方法调用。
%Symbol.toPrimitive% "Symbol.toPrimitive" 一个方法,将对象转换为对应的原始值。由 ToPrimitive 抽象 操作调用。
%Symbol.toStringTag% "Symbol.toStringTag" 一个 String 值属性,用于创建对象的默认字符串描述。由内建 方法 Object.prototype.toString 访问。
%Symbol.unscopables% "Symbol.unscopables" 一个对象值属性,其自有和继承属性名,都是从关联对象的 with 环境绑定中排除的属性名

6.1.6 数值类型

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

Table 2: 数值类型操作
操作 示例源码 由……的 Evaluation 语义调用 结果
Number::unaryMinus -x 一元 - 运算符 Number
BigInt::unaryMinus BigInt
Number::bitwiseNOT ~x 按位非运算符 ( ~ ) Number
BigInt::bitwiseNOT BigInt
Number::exponentiate x ** y 指数运算符Math.pow ( base, exponent ) Number
BigInt::exponentiate 要么是包含 BigInt 的正常完成,要么是抛出完成
Number::multiply x * y 乘法运算符 Number
BigInt::multiply BigInt
Number::divide x / y 乘法运算符 Number
BigInt::divide 要么是包含 BigInt 的正常完成,要么是抛出完成
Number::remainder x % y 乘法运算符 Number
BigInt::remainder 要么是包含 BigInt 的正常完成,要么是抛出完成
Number::add x ++
++ x
x + y
后缀递增运算符前缀递增运算符、 和 加法运算符 ( + ) Number
BigInt::add BigInt
Number::subtract x --
-- x
x - y
后缀递减运算符前缀递减运算符、 和 减法运算符 ( - ) Number
BigInt::subtract BigInt
Number::leftShift x << y 左移运算符 ( << ) Number
BigInt::leftShift BigInt
Number::signedRightShift x >> y 有符号右移运算符 ( >> ) Number
BigInt::signedRightShift BigInt
Number::unsignedRightShift x >>> y 无符号右移运算符 ( >>> ) Number
BigInt::unsignedRightShift 一个抛出完成
Number::lessThan x < y
x > y
x <= y
x >= y
关系运算符, 通过 IsLessThan ( x, y, leftFirst ) Boolean 或 undefined(对于无序输入)
BigInt::lessThan Boolean
Number::equal x == y
x != y
x === y
x !== y
相等运算符, 通过 IsStrictlyEqual ( x, y ) Boolean
BigInt::equal
Number::sameValue Object.is(x, y) Object 内部方法, 通过 SameValue ( x, y ), 用于测试精确值相等 Boolean
Number::sameValueZero [x].includes(y) 通过 SameValueZero ( x, y ), 用于测试值相等,并忽略 +0𝔽-0𝔽 之间的差异,如 Array、Map 和 Set 方法中那样 Boolean
Number::bitwiseAND x & y 二元按位运算符 Number
BigInt::bitwiseAND BigInt
Number::bitwiseXOR x ^ y Number
BigInt::bitwiseXOR BigInt
Number::bitwiseOR x | y Number
BigInt::bitwiseOR BigInt
Number::toString String(x) 许多表达式和内建函数,通过 ToString ( 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 二进制浮点运算标准中规定的 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 zero 也有 negative 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 值最接近的成员。若集合中的两个值与 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 ( 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 的相反数;即,计算一个大小相同但符号相反的 Number。

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. 它返回一个实现近似值,表示 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 是奇数整数 Number,返回 -∞𝔽
      2. 返回 +∞𝔽
    2. exponent 是奇数整数 Number,返回 -0𝔽
    3. 返回 +0𝔽
  6. base+0𝔽,则
    1. exponent > +0𝔽,返回 +0𝔽
    2. 返回 +∞𝔽
  7. base-0𝔽,则
    1. exponent > +0𝔽,则
      1. exponent 是奇数整数 Number,返回 -0𝔽
      2. 返回 +0𝔽
    2. exponent 是奇数整数 Number,返回 -∞𝔽
    3. 返回 +∞𝔽
  8. 断言:base有限值,且既不是 +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 不是整数 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. 它按照 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 (一个 Number,) and y (一个 Number,) and returns 一个 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 ( n, d )

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

  1. nNaNdNaN,返回 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 所定义的 “remainder” 操作并不相同。IEEE 754-2019 的 “remainder” 操作计算的是舍入除法所得的余数,而不是截断除法, 因此它的行为与通常的整数余数运算符并不 类比。相反,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. 它按照 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 (一个 Number,) and y (一个 Number,) and returns 一个 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 (一个 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) modulo 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) modulo 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) modulo 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. 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 (一个 Number,) and y (一个 Number,) and returns 一个 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 (一个 Number,) and y (一个 Number,) and returns 一个 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 (一个 Number,) and y (一个 Number,) and returns 一个 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 (&^|,), 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 应用按位异或(XOR) 运算的结果。
  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 一个 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 尽可能小。注意,ks 以基数 radix 表示时的位数,s 不可被 radix 整除,并且 s 的最低有效位不一定由这些条件唯一确定。
  6. radix ≠ 10 或 n 位于 -5 到 21 的闭区间内,则
    1. nk,则
      1. 返回以下内容的字符串连接
        • s 以基数 radix 表示的 k 位数字的码元
        • n - k 个码元 0x0030(DIGIT ZERO)
    2. n > 0,则
      1. 返回以下内容的字符串连接
        • s 以基数 radix 表示的最高有效 n 位数字的码元
        • 码元 0x002E(FULL STOP)
        • s 以基数 radix 表示的剩余 k - n 位数字的码元
    3. 断言:n ≤ 0。
    4. 返回以下内容的字符串连接
      • 码元 0x0030(DIGIT ZERO)
      • 码元 0x002E(FULL STOP)
      • -n 个码元 0x0030(DIGIT ZERO)
      • s 以基数 radix 表示的 k 位数字的码元
  7. 注:在这种情况下,输入会使用科学计数法 E 记法表示,例如 1.2e+3
  8. 断言:radix 是 10。
  9. n < 0,则
    1. exponentSign 为码元 0x002D(HYPHEN-MINUS)。
  10. 否则,
    1. exponentSign 为码元 0x002B(PLUS SIGN)。
  11. k = 1,则
    1. 返回以下内容的字符串连接
      • s 的单个数字对应的码元
      • 码元 0x0065(LATIN SMALL LETTER E)
      • exponentSign
      • abs(n - 1) 的十进制表示的码元
  12. 返回以下内容的字符串连接
    • s 的十进制表示中最高有效数字的码元
    • 码元 0x002E(FULL STOP)
    • s 的十进制表示中剩余 k - 1 位数字的码元
    • 码元 0x0065(LATIN SMALL LETTER E)
    • exponentSign
    • abs(n - 1) 的十进制表示的码元
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,则选择偶数那个。注意,ks 以基数 radix 表示时的位数,且 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. Available as
https://ampl.com/_archive/first-website/REFS/rounding.pdf. Associated code available as
http://netlib.sandia.gov/fp/dtoa.c and as
http://netlib.sandia.gov/fp/g_fmt.c and may also be found at the various netlib mirror sites.

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. 它返回 x 的一补数。 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
  2. 返回 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
  2. 返回 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 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. tmpBinaryAnd(x modulo 2, y modulo 2)。
  7. 否则若 op|,则
    1. tmpBinaryOr(x modulo 2, y modulo 2)。
  8. 否则,
    1. 断言:op^
    2. tmpBinaryXor(x modulo 2, y modulo 2)。
  9. tmp ≠ 0,则
    1. result 设为 result - 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 一个 String. 它使用基数为 radix 的位值计数系统将 x 表示为一个 String。使用基数 r 表示 BigInt 时所用的数字字符,按顺序取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个码元。除 0 之外的 BigInt 的表示绝不会包含前导零。 It performs the following steps when called:

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

6.1.7 Object 类型

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

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

对象的属性通过属性键被唯一标识。属性键 是 String 或 Symbol 之一。所有 String 和 Symbol,包括空 String, 都可以作为合法的属性键属性名是一个属于 String 的属性键

整数索引 是这样一个属性名 nCanonicalNumericIndexString(n) 返回一个位于 +0𝔽𝔽(253 - 1) 闭区间内的 整数 Number数组索引是这样一个整数索引 nCanonicalNumericIndexString(n) 返回一个位于 +0𝔽𝔽(232 - 2) 闭区间内的 整数 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 对象内部方法和内部槽

在 ECMAScript 中,对象的实际语义是通过称为内部方法 的算法来规定的。ECMAScript 引擎中的每个对象都关联着一组定义其运行时 行为的内部方法。这些内部方法不是 ECMAScript 语言的一部分。它们仅为 说明之用而由本规范定义。然而,ECMAScript 实现中的每个对象都必须按与 其关联的内部方法所规定的方式表现。具体如何做到这一点由实现决定。

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

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

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

本规范中,内部方法和内部槽使用置于双重方括号 [[ ]] 中的名称 标识。

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

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

  • 对于 Table 4 中列出的内部方法,该对象使用 10.1 中定义的方法。
  • 若该对象具有 [[Call]] 内部方法,则它使用 10.2.110.3.1 中定义的方法。
  • 若该对象具有 [[Construct]] 内部方法,则它使用 10.2.210.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, propertyDescriptor) Boolean 创建或修改键为 propertyKey 的自有属性,使其具有 propertyDescriptor 所描述的状态。若该属性成功创建/更新 则返回 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 返回一个 List,其元素为该对象的全部自有属性键

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

Table 5: 函数对象的附加基本内部方法
内部方法 签名 描述
[[Call]] (any, 一个 anyList) any 执行与该对象关联的代码。通过函数调用表达式调用。传给该内部 方法的参数是一个 this 值以及一个 List,该 List 的元素 是调用表达式传给函数的参数。实现此内部方法的对象称为 可调用对象。
[[Construct]] (一个 anyList, Object) Object 创建一个对象。通过 new 运算符或 super 调用来调用。 该内部方法的第一个参数是一个 List,其元素是构造器调用或 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 completion、break completion 或 return completion。

[[GetPrototypeOf]] ( )

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

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

[[SetPrototypeOf]] ( proto )

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

[[IsExtensible]] ( )

  • 正常返回类型是 Boolean。
  • [[IsExtensible]] 返回 false,则之后对该目标调用 [[IsExtensible]] 必须始终返回 false

[[PreventExtensions]] ( )

  • 正常返回类型是 Boolean。
  • [[PreventExtensions]] 返回 true,则之后对该目标调用 [[IsExtensible]] 必须始终返回 false,并且该目标现在被视为 不可扩展。

[[GetOwnProperty]] ( propertyKey )

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

由第三个不变量可知,若某属性被描述为数据属性,且它可能随时间 返回不同的值,那么即使没有通过其他基本内部方法暴露修改该值的机制, [[Writable]][[Configurable]] 特性中至少有一个必须为 true

[[DefineOwnProperty]] ( propertyKey, desc )

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

[[HasProperty]] ( propertyKey )

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

[[Get]] ( propertyKey, receiver )

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

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

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

[[Delete]] ( propertyKey )

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

[[OwnPropertyKeys]] ( )

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

[[Call]] ( )

[[Construct]] ( )

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

6.1.7.4 众所周知的内在对象

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

在本规范中,诸如 %name% 这样的引用表示与当前 realm 关联的、 名称对应的那个内在对象。诸如 %name.a.b% 这样的引用表示:仿佛在任何 ECMAScript 代码求值之前,已经访问了内在对象 %name% 的属性 "a" 的 值的属性 "b"。当前 realm 及其内在值的确定见 9.4。众所周知的 内在值列于 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
%AsyncFromSyncIteratorPrototype% Async-from-Sync Iterator 对象的原型(27.1.5
%AsyncFunction% async function 对象的构造器27.7.1
%AsyncGeneratorFunction% async generator function 对象的构造器27.4.1
%AsyncGeneratorPrototype% async generator 对象的原型(27.6
%AsyncIteratorPrototype% 所有标准内建异步迭代器对象间接继承自它的一个对象
%Atomics% Atomics Atomics 对象( 25.4
%BigInt% BigInt BigInt 构造器21.2.1
%BigInt64Array% BigInt64Array BigInt64Array 构造器23.2
%BigUint64Array% BigUint64Array BigUint64Array 构造器23.2
%Boolean% Boolean Boolean 构造器20.3.1
%DataView% DataView DataView 构造器25.3.2
%Date% Date Date 构造器21.4.2
%decodeURI% decodeURI decodeURI 函数(19.2.6.1
%decodeURIComponent% decodeURIComponent decodeURIComponent 函数(19.2.6.2
%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.3.1
%GeneratorPrototype% generator 对象的原型(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 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.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% 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
%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 返回的包装迭代器对象的原型(27.1.3.2.2.1
Note

Table 98 中还有附加条目。

6.2 ECMAScript 规范类型

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

6.2.1 Enum 规范类型

Enum 是规范内部使用、而不能被 ECMAScript 代码直接观察到的值。Enum 使用全大写 kebab case,并以 sans-serif 字体表示。例如,Completion Record[[Type]] 字段会 取 normalreturnthrow 之类的值。Enum 除其名称外不具有 其他特征。Enum 的名称除了将其与其他 enum 区分开来之外没有别的用途, 也不暗示其在上下文中的用法或含义。

6.2.2 List 和 Record 规范类型

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

当算法遍历 List 的元素而未指定顺序时,所使用的顺序就是 List 中 元素的顺序。

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

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

对于 String 的 List,短语“按码元字典序排序”表示:按每个 码元的数值比较,比较到较短字符串的长度为止;若此前都相等,则较短字符串 排在较长字符串之前,正如抽象操作 IsLessThan 所描述的那样。

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

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

在规范文本和算法中,可使用点记法来引用 Record 值中的某个特定 字段。例如,若 R 是前一段所示的 record,则 R.[[Field2]] 是“R 中名为 [[Field2]] 的字段”的简写。

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

6.2.3 Set 和 Relation 规范类型

Set 类型用于说明内存模型中使用的无序元素集合。它不同于 同名的 ECMAScript 集合类型。为避免歧义,在本规范中,ECMAScript 集合的 实例一律称为 “Set objects”。Set 类型的值是元素的简单集合,其中不会有 元素重复出现。元素可以添加到 Set 中,也可以从 Set 中移除。Set 可以彼此 求并集、交集或差集。

Relation 类型用于说明 Set 上的 约束。Relation 类型的值是由其值域中的值组成的有序对的 Set。例如, 内存事件上的 Relation 是一组内存事件的有序对。对于一个 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 Record 具有 Table 7 中定义的字段。

Table 7: Completion Record 字段
字段名称 含义
[[Type]] normalbreakcontinuereturnthrow 发生的完成类型。
[[Value]] 任何值,但不能是 Completion Record 所产生的值。
[[Target]] 一个 String 或 empty 定向控制转移的目标标签。

下面这些简写术语有时用于指代 Completion Record。

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

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

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

6.2.4.1 NormalCompletion ( value )

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 一个抛出完成. 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 Record, 或 unresolvable 持有该绑定的值或 Environment Record[[Base]]unresolvable 表示该绑定无法解析。
[[ReferencedName]] 一个 ECMAScript 语言值或一个 Private Name 绑定的名称。若 [[Base]] 值是 Environment Record,则它 始终是一个 String。否则,在执行 ToPropertyKey 之前,它可以是除 String 或 Symbol 之外的 ECMAScript 语言值
[[Strict]] 一个 Boolean 若该 Reference Record 来源于严格模式代码,则为 true; 否则为 false
[[ThisValue]] 一个 ECMAScript 语言值empty 若不是 empty,则该 Reference Record 表示一个使用 super 关键字表达的属性绑定;它被称为 Super Reference Record, 并且其 [[Base]] 值绝不会是 Environment Record。在这种情况下, [[ThisValue]] 字段保存创建该 Reference Record 时的 this 值。

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

6.2.5.1 IsPropertyReference ( referenceRecord )

The abstract operation IsPropertyReference takes argument referenceRecord (一个 Reference Record,) and returns 一个 Boolean. It performs the following steps when called:

  1. referenceRecord.[[Base]]unresolvable,返回 false
  2. referenceRecord.[[Base]] 是一个 Environment Record, 返回 false
  3. 返回 true

6.2.5.2 IsUnresolvableReference ( referenceRecord )

The abstract operation IsUnresolvableReference takes argument referenceRecord (一个 Reference Record,) and returns 一个 Boolean. It performs the following steps when called:

  1. referenceRecord.[[Base]]unresolvable,返回 true
  2. 返回 false

6.2.5.3 IsSuperReference ( referenceRecord )

The abstract operation IsSuperReference takes argument referenceRecord (一个 Reference Record,) and returns 一个 Boolean. It performs the following steps when called:

  1. referenceRecord.[[ThisValue]]empty,返回 false
  2. 返回 true

6.2.5.4 IsPrivateReference ( referenceRecord )

The abstract operation IsPrivateReference takes argument referenceRecord (一个 Reference Record,) and returns 一个 Boolean. It performs the following steps when called:

  1. referenceRecord.[[ReferencedName]] 是一个 Private Name, 返回 true
  2. 返回 false

6.2.5.5 GetValue ( referenceRecord )

The abstract operation GetValue takes argument referenceRecord (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. referenceRecord 不是 Reference Record,返回 referenceRecord
  2. IsUnresolvableReference(referenceRecord) 是 true, 抛出一个 ReferenceError 异常。
  3. IsPropertyReference(referenceRecord) 是 true,则
    1. baseObj 为 ? ToObject(referenceRecord.[[Base]])。
    2. IsPrivateReference(referenceRecord) 是 true,则
      1. 返回 ? PrivateGet(baseObj, referenceRecord.[[ReferencedName]])。
    3. referenceRecord.[[ReferencedName]] 不是属性键,则
      1. referenceRecord.[[ReferencedName]] 设为 ? ToPropertyKey(referenceRecord.[[ReferencedName]])。
    4. 返回 ? baseObj.[[Get]] (referenceRecord.[[ReferencedName]], GetThisValue(referenceRecord))
  4. basereferenceRecord.[[Base]]
  5. 断言:base 是一个 Environment Record
  6. 返回 ? base.GetBindingValue( referenceRecord.[[ReferencedName]], referenceRecord.[[Strict]])(见 9.1)。
Note

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

6.2.5.6 PutValue ( referenceRecord, value )

The abstract operation PutValue takes arguments referenceRecord (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. referenceRecord 不是 Reference Record,抛出一个 ReferenceError 异常。
  2. IsUnresolvableReference(referenceRecord) 是 true,则
    1. referenceRecord.[[Strict]]true,抛出一个 ReferenceError 异常。
    2. globalObjGetGlobalObject()。
    3. 执行 ? Set(globalObj, referenceRecord.[[ReferencedName]], value, false)。
    4. 返回 unused
  3. IsPropertyReference(referenceRecord) 是 true,则
    1. baseObj 为 ? ToObject(referenceRecord.[[Base]])。
    2. IsPrivateReference(referenceRecord) 是 true,则
      1. 返回 ? PrivateSet(baseObj, referenceRecord.[[ReferencedName]], value)。
    3. referenceRecord.[[ReferencedName]] 不是属性键,则
      1. referenceRecord.[[ReferencedName]] 设为 ? ToPropertyKey(referenceRecord.[[ReferencedName]])。
    4. succeeded 为 ? baseObj.[[Set]](referenceRecord.[[ReferencedName]], value, GetThisValue(referenceRecord))
    5. succeededfalsereferenceRecord.[[Strict]]true,抛出一个 TypeError 异常。
    6. 返回 unused
  4. basereferenceRecord.[[Base]]
  5. 断言:base 是一个 Environment Record
  6. 返回 ? base.SetMutableBinding( referenceRecord.[[ReferencedName]], value, referenceRecord.[[Strict]])(见 9.1)。
Note

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

6.2.5.7 GetThisValue ( referenceRecord )

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

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

6.2.5.8 InitializeReferencedBinding ( referenceRecord, value )

The abstract operation InitializeReferencedBinding takes arguments referenceRecord (一个 Reference Record,) and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是突兀完成. It performs the following steps when called:

  1. 断言:IsUnresolvableReference(referenceRecord) 是 false
  2. basereferenceRecord.[[Base]]
  3. 断言:base 是一个 Environment Record
  4. 返回 ? base.InitializeBinding( referenceRecord.[[ReferencedName]], value)。

6.2.5.9 MakePrivateReference ( baseValue, privateIdentifier )

The abstract operation MakePrivateReference takes arguments baseValue (一个 ECMAScript 语言值,) and privateIdentifier (一个 String,) 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 类型用于说明 Object 属性特性的操作和具体化。Property Descriptor 是 一个具有零个或多个字段的 Record,其中每个字段名都是一个特性名, 其值是 6.1.7.1 中 规定的对应特性值。本规范中用于标记 Property Descriptor record 字面量 描述的 schema 名称是 “PropertyDescriptor”。

Property Descriptor 值还可以根据某些字段的存在或使用进一步分为 数据 Property Descriptor 和访问器 Property Descriptor。数据 Property Descriptor 是包含名为 [[Value]][[Writable]] 的任一字段 的 Property Descriptor。访问器 Property Descriptor 是包含名为 [[Get]][[Set]] 的任一字段的 Property Descriptor。任何 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 ( desc )

The abstract operation IsAccessorDescriptor takes argument desc (一个 Property Descriptor,) and returns 一个 Boolean. 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 一个 Boolean. 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 一个 Boolean. 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 一个 Object 或 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 不是 Object,抛出一个 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]] 字段或 desc 具有 [[Set]] 字段,则
    1. desc 具有 [[Value]] 字段或 desc 具有 [[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 时应执行的算法步骤中, 每个被捕获的值都通过用来捕获它的那个别名来引用。

若某个 Abstract Closure 返回 Completion Record,那么该 Completion Record 必须是正常完成或抛出完成之一。

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

Data Block 规范类型用于描述一段 独立且可变的、由字节大小(8 位)数值构成的序列。字节值是位于 0 到 255 闭区间内的整数。一个 Data Block 值在创建时具有固定数量的字节,这些字节的初始值都为 0。

为便于本规范中的记号表达,可以使用类似数组的语法来访问 Data Block 值中的单个字节。该记法将 Data Block 值表现为一个以 0 为起始索引 的字节序列。比如,若 db 是一个 5 字节的 Data Block 值,则可使用 db[2] 来访问它的第 3 个字节。

驻留在可被多个 agent 并发引用的内存中的 data block 被指定为 Shared Data Block。Shared Data Block 具有一种标识(用于 Shared Data Block 值的相等性测试), 这种标识是与地址无关的:它不绑定于该 block 在任何进程中映射到 的虚拟地址,而是绑定于该 block 所表示的内存位置集合。只有当两个 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. agentRecord外围 agentAgent Record
  3. executionagentRecord.[[CandidateExecution]]
  4. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
  5. zero 为 « 0 »。
  6. db 的每个索引 i,执行
    1. 将 WriteSharedMemory { [[Order]]: init, [[NoTear]]: true, [[Block]]: db, [[ByteIndex]]: i, [[ElementSize]]: 1, [[Payload]]: zero } 追加到 eventsRecord.[[EventList]]
  7. 返回 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. agentRecord外围 agentAgent Record
      2. executionagentRecord.[[CandidateExecution]]
      3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
      4. bytes 为一个 List,其唯一元素是一个以非确定方式选取 的字节值
      5. 注:在实现中,bytes 是底层硬件上一条非原子读取指令的 结果。这里的非确定性是内存模型的一种语义规定,用来描述 弱一致性硬件的可观察行为。
      6. readEvent 为 ReadSharedMemory { [[Order]]: unordered, [[NoTear]]: true, [[Block]]: fromBlock, [[ByteIndex]]: fromIndex, [[ElementSize]]: 1 }。
      7. readEvent 追加到 eventsRecord.[[EventList]]
      8. Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: bytes } 追加到 execution.[[ChosenValues]]
      9. 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 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 Record

Table 10: ClassFieldDefinition Record 字段
字段名称 含义
[[Name]] 一个 Private Name、一个 String 或一个 Symbol 字段的名称。
[[Initializer]] 一个 ECMAScript 函数对象empty 字段的初始化器(若存在)。

6.2.12 Private Name

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

6.2.13 ClassStaticBlockDefinition Record 规范类型

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

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

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