5.1 句法和词法文法
5.1.1 上下文无关文法
上下文无关文法由若干产生式组成。每个产生式都有一个抽象符号,称为非终结符,作为其左部,以及由零个或多个非终结符和终结符组成的序列,作为其右部。对于每个文法,终结符来自指定的字母表。
链式产生式是指其右部恰好只有一个非终结符和零个或多个终结符的产生式。
从一个仅包含单一特殊非终结符的句子开始,称为目标符号,给定的上下文无关文法定义了一个语言,即通过不断将序列中的任意非终结符替换为以该非终结符为左部的某个产生式的右部,最终可能得到的所有终结符序列的集合(可能是无限的)。
5.1.2 词法和正则表达式文法
ECMAScript 的词法文法见 12。该文法的终结符是符合 11.1 中 SourceCharacter 规则的 Unicode 码点。它定义了一组产生式,从目标符号 InputElementDiv、InputElementTemplateTail、InputElementRegExp、InputElementRegExpOrTemplateTail 或 InputElementHashbangOrRegExp 开始,描述了这些码点序列如何转换为输入元素序列。
除空白和注释外的输入元素构成 ECMAScript 句法文法的终结符,被称为 ECMAScript 标记。这些标记包括 ECMAScript 语言的保留字、标识符、字面量和标点符号。此外,行终止符虽然不是标记,但也成为输入元素流的一部分,引导自动分号插入过程(12.10)。简单空白和单行注释会被丢弃,不会出现在句法文法的输入元素流中。MultiLineComment(即形如 /*
…*/
的注释,无论是否跨越多行)如果不包含行终止符,则同样被丢弃;但若包含一个或多个行终止符,则被替换为一个单一行终止符,后者成为句法文法输入元素流的一部分。
ECMAScript 的正则表达式文法见 22.2.1。该文法的终结符同样为 SourceCharacter 所定义的码点。它定义了一组产生式,从目标符号 Pattern 开始,描述了码点序列如何转换为正则表达式模式。
词法和正则表达式文法的产生式以两个冒号“::”作为分隔标志。词法文法和正则表达式文法共享部分产生式。
5.1.3 数值字符串文法
数值字符串文法见 7.1.4.1。其终结符为 SourceCharacter,用于将字符串从目标符号 StringNumericLiteral 开始转换为数值(与 数值字面量的词法文法 类似但不同)。
数值字符串文法的产生式以三个冒号“:::”为标点,并从不用于解析源文本。
5.1.4 句法文法
ECMAScript 的句法文法见 13 到 16。该文法的终结符为词法文法定义的 ECMAScript 标记(5.1.2)。它定义了一组产生式,从两个备选目标符号 Script 和 Module 开始,描述了标记序列如何组成语法正确的 ECMAScript 程序独立组件。
当要将码点流解析为 ECMAScript 的 Script 或 Module 时,首先通过反复应用词法文法,将其转换为输入元素流;然后该输入元素流通过一次句法文法解析。若输入元素流中的标记无法解析为一个目标非终结符(Script 或 Module)的实例,且没有剩余标记,则输入流存在语法错误。
解析成功时会构建一个解析树,即以根为起点的树结构,每个节点为一个解析节点。每个解析节点是文法符号的一个实例,表示可由该符号导出的源文本片段。解析树的根节点,代表整个源文本,是解析目标符号的一个实例。当解析节点是非终结符的实例时,也是以该非终结符为左部的某个产生式的实例。此外,它有零个或多个子节点,每个对应产生式右部的一个符号:每个子节点是相应符号的解析节点实例。
每次解析器调用都会实例化新的解析节点,即使解析的源文本完全相同,解析节点也不会复用。只有当解析节点代表同一源文本片段、是同一文法符号的实例且来源于同一次解析器调用时,才认为它们是同一个解析节点。
Note 1
多次解析同一个字符串会得到不同的解析节点。例如:
let str = "1 + 1;";
eval(str);
eval(str);
每次调用 eval
都会将 str
的值转换为 ECMAScript 源文本,并进行独立解析,生成各自独立的解析节点树。即使每次解析的源文本都来自同一个字符串值,树结构也是不同的。
Note 2解析节点是规范中的抽象实体,具体实现无需采用类似的数据结构。
句法文法的产生式以单个冒号“:”作为标点。
在 13 到 16 条款中呈现的句法文法并未完全覆盖所有可作为正确 ECMAScript Script 或 Module 被接受的标记序列。额外接受的标记序列包括那些仅需在某些位置(如行终止符前)添加分号即可被文法描述的序列。此外,某些文法描述的标记序列若在某些“特殊”位置出现行终止符,则不被接受。
为避免歧义,句法文法在某些情况下使用了广义产生式,允许不形成有效 ECMAScript Script 或 Module 的标记序列。例如,对象字面量和对象解构模式采用此技术。在这些情况下,会提供更严格的补充文法以进一步限制可接受的标记序列。一般情况下,早期错误规则会规定,在某些上下文中,“P 必须覆盖 N”,其中 P 是解析节点(广义产生式的实例),N 是补充文法中的非终结符。这表示:
- 对 P 最初匹配的标记序列,以 N 作为目标符号再次解析。如果 N 有文法参数,则使用 P 最初解析时的参数值。
- 如果标记序列能作为 N 的唯一实例解析,且无剩余标记,则:
- 我们称该实例(唯一对应于某个 P 的解析节点)为“P 所覆盖的 N”。
- 所有对 N 及其派生产生式的早期错误规则也适用于 P 所覆盖的 N。
- 否则(解析失败),则为早期语法错误。
5.1.5 文法记号
5.1.5.1 终结符号
在 ECMAScript 文法中,部分终结符以 等宽字体
展示。这些符号应在源文本中完全按原样出现。此类终结符指定的所有码点均应理解为基本拉丁区(Basic Latin block)中对应的 Unicode 码点,不包括其他 Unicode 区段中外观相似的码点。终结符中的码点不能用 \
UnicodeEscapeSequence 表示。
在以单个 Unicode 码点为终结符的文法(即词法、正则和数值字符串文法)中,产生式中连续出现的多个等宽码点是一种简写,表示同样顺序的独立终结符。
例如如下产生式:
HexIntegerLiteral ::
0x
HexDigits
是如下写法的简写:
HexIntegerLiteral ::
0
x
HexDigits
而在句法文法中,连续的等宽码点则视为单一终结符。
终结符还可以有两种形式:
5.1.5.2 非终结符号和产生式
非终结符以斜体展示。非终结符的定义(也称“产生式”)由被定义的非终结符名称后跟一个或多个冒号引出。(冒号数量表明该产生式属于哪种文法。)随后为该非终结符的一个或多个备选右部。例如,句法定义:
WhileStatement :
while
(
Expression
)
Statement
说明非终结符 WhileStatement 表示标记 while
,后跟左括号标记,再跟 Expression,再跟右括号标记,最后跟 Statement。其中 Expression 和 Statement 本身也是非终结符。另一个例子,句法定义:
ArgumentList :
AssignmentExpression
ArgumentList
,
AssignmentExpression
说明 ArgumentList 可以表示单个 AssignmentExpression,或 ArgumentList 后跟逗号,再跟 AssignmentExpression。该定义是递归的,即用自身定义自身。因此 ArgumentList 可包含任意数量且大于零的参数,每个参数表达式为 AssignmentExpression,参数间以逗号分隔。此类递归定义很常见。
5.1.5.3 可选符号
下标后缀“opt”用于终结符或非终结符之后,表示该符号为可选。包含可选符号的备选实际上指定了两个右部:一个省略可选元素,一个包含可选元素。即:
VariableDeclaration :
BindingIdentifier
Initializeropt
是如下写法的简写:
VariableDeclaration :
BindingIdentifier
BindingIdentifier
Initializer
同理:
ForStatement :
for
(
LexicalDeclaration
Expressionopt
;
Expressionopt
)
Statement
是如下写法的简写:
ForStatement :
for
(
LexicalDeclaration
;
Expressionopt
)
Statement
for
(
LexicalDeclaration
Expression
;
Expressionopt
)
Statement
进一步简写为:
ForStatement :
for
(
LexicalDeclaration
;
)
Statement
for
(
LexicalDeclaration
;
Expression
)
Statement
for
(
LexicalDeclaration
Expression
;
)
Statement
for
(
LexicalDeclaration
Expression
;
Expression
)
Statement
所以在此例中,非终结符 ForStatement 实际有四个备选右部。
5.1.5.4 文法参数
产生式可以通过下标标注“[参数]”进行参数化,该标注可作为产生式定义的非终结符后缀。“参数”可以是单个名称或以逗号分隔的名称列表。参数化产生式是对一组产生式的简写,定义了所有参数名称组合,组合名以下划线为前缀,附加到参数化非终结符后。即:
StatementList[Return] :
ReturnStatement
ExpressionStatement
是如下写法的简写:
StatementList :
ReturnStatement
ExpressionStatement
StatementList_Return :
ReturnStatement
ExpressionStatement
同理:
StatementList[Return, In] :
ReturnStatement
ExpressionStatement
是如下写法的简写:
StatementList :
ReturnStatement
ExpressionStatement
StatementList_Return :
ReturnStatement
ExpressionStatement
StatementList_In :
ReturnStatement
ExpressionStatement
StatementList_Return_In :
ReturnStatement
ExpressionStatement
多个参数会生成组合数量的产生式,但完整文法中并不一定全部引用。
产生式右部对非终结符的引用也可以参数化。例如:
StatementList :
ReturnStatement
ExpressionStatement[+In]
等价于:
StatementList :
ReturnStatement
ExpressionStatement_In
而:
StatementList :
ReturnStatement
ExpressionStatement[~In]
等价于:
StatementList :
ReturnStatement
ExpressionStatement
非终结符引用可以同时有参数列表和“opt”后缀。例如:
VariableDeclaration :
BindingIdentifier
Initializer[+In]opt
简写为:
VariableDeclaration :
BindingIdentifier
BindingIdentifier
Initializer_In
在右部非终结符引用上用“?”作为参数名前缀,使该参数取值依赖于当前产生式左部符号引用是否出现该参数。例如:
VariableDeclaration[In] :
BindingIdentifier
Initializer[?In]
是如下写法的简写:
VariableDeclaration :
BindingIdentifier
Initializer
VariableDeclaration_In :
BindingIdentifier
Initializer_In
如果右部备选以“[+参数]”为前缀,表示仅当引用产生式非终结符时使用了该参数名才可用该备选。如果以“[~参数]”为前缀,则仅在未使用该参数名时可用该备选。即:
StatementList[Return] : [+Return]
ReturnStatement
ExpressionStatement
简写为:
StatementList :
ExpressionStatement
StatementList_Return :
ReturnStatement
ExpressionStatement
同理:
StatementList[Return] : [~Return]
ReturnStatement
ExpressionStatement
简写为:
StatementList :
ReturnStatement
ExpressionStatement
StatementList_Return :
ExpressionStatement
5.1.5.5 one of
当“one of”出现在文法定义中的冒号后,表示后续每个终结符都是一个备选定义。例如 ECMAScript 的词法文法包含如下产生式:
NonZeroDigit :: one of 1 2 3 4 5 6 7 8 9
实际上是如下简写:
NonZeroDigit ::
1
2
3
4
5
6
7
8
9
5.1.5.6 [empty]
如果“[empty]”出现在产生式右部,表示该产生式右部不包含任何终结符或非终结符。
5.1.5.7 前瞻限制
若“[lookahead = seq]”出现在产生式右部,表示只有当标记序列 seq 是紧跟输入标记序列的前缀时,才能使用该产生式。同理,“[lookahead ∈ set]”,其中 set 为有限非空标记序列集合,表示只有当集合中的某个元素是紧跟输入标记序列的前缀时才能使用该产生式。为了方便,也可以将集合写为非终结符,此时表示该非终结符可能扩展到的所有标记序列。若非终结符能扩展为无限多种不同标记序列,则视为编辑错误。
这些条件可以取反。“[lookahead ≠ seq]”表示只有当 seq 不是紧跟输入标记序列的前缀时才能使用该产生式,而“[lookahead ∉ set]”表示只有当集合中无元素是紧跟输入标记序列的前缀时才能使用该产生式。
例如,给定如下定义:
DecimalDigit :: one of 0 1 2 3 4 5 6 7 8 9
DecimalDigits ::
DecimalDigit
DecimalDigits
DecimalDigit
则如下定义:
LookaheadExample ::
n
[lookahead ∉ { 1, 3, 5, 7, 9 }]
DecimalDigits
DecimalDigit
[lookahead ∉ DecimalDigit]
匹配字符 n
后跟一个或多个十进制数字,且首位为偶数,或匹配一个十进制数字且后面不再有十进制数字。
注意,这些短语用于句法文法时,可能无法明确识别紧跟的标记序列,因为确定后续标记需要知道后续使用哪个词法目标符号。因此,在句法文法中使用这些短语时,若前缀标记序列 seq 的词法目标符号选择会影响其是否作为结果标记序列前缀,则视为编辑错误。
若“[no LineTerminator here]”出现在句法文法产生式右部,表示该产生式为受限产生式:若在指定位置的输入流中出现 LineTerminator,则不能使用该产生式。例如如下产生式:
ThrowStatement :
throw
[no LineTerminator here]
Expression
;
表示若在脚本中的 throw
标记和 Expression 之间出现 LineTerminator,则不能使用该产生式。
除非受限产生式禁止出现 LineTerminator,否则在输入元素流的任意两个连续标记之间可以出现任意数量的 LineTerminator,不会影响脚本的语法合法性。
5.1.5.9 but not
产生式右部可用“but not”短语指定某些扩展不允许。例如如下产生式:
Identifier ::
IdentifierName but not ReservedWord
表示非终结符 Identifier 可替换为可替换 IdentifierName 的任何码点序列,但不能替换为可替换 ReservedWord 的同一序列。
5.1.5.10 描述性短语
最后,少数非终结符用无衬线字体描述性短语来说明,当枚举所有备选项不切实际时使用:
SourceCharacter ::
任意 Unicode 码点
5.2 算法约定
规范经常使用编号列表来指定算法步骤。这些算法用于精确定义 ECMAScript 语言结构所需的语义。算法并不意味着必须采用任何特定的实现技术。实际应用中,可能有更高效的算法可用于实现某个特性。
算法可以显式使用有序、逗号分隔的别名序列进行参数化,在算法步骤中可以通过这些别名引用对应位置传入的参数。可选参数用括号([ , name ])标记,在算法步骤中与必选参数没有区别。参数列表末尾可以出现剩余参数,用前置省略号(, ...name)标记。剩余参数会将所有必选和可选参数之后传入的参数收集到一个 List 中。如果没有额外参数,则该 List 为空。
算法步骤可以细分为顺序子步骤。子步骤缩进显示,并且自身可以进一步划分为缩进子步骤。大纲编号用于标识子步骤:第一层使用小写字母,第二层使用小写罗马数字。如需超过三层,则第四层用数字编号。例如:
- 顶层步骤
- 子步骤。
- 子步骤。
- 子子步骤。
- 子子子步骤
- 子子子子步骤
- 子子子子子步骤
某个步骤或子步骤可以写成“if”条件,控制其子步骤。此时,只有条件为真时才执行子步骤。如果步骤或子步骤以“else”开头,则表示该条件是同级前一个“if”条件的否定。
步骤可以指定对子步骤的迭代应用。
以“Assert:”开头的步骤表示断言该算法的不变条件。这样的断言用于显式表达本应隐含的算法不变量,不增加语义要求,因此实现无需检查。它们仅用于澄清算法。
算法步骤可以用“Let x be someValue”声明命名别名。这些别名类似引用,即 x 和 someValue 都引用相同的数据,对任一的修改都可见。若算法步骤希望避免引用行为,应显式复制右侧值:“Let x be a copy of someValue”会创建 someValue 的浅复制。
别名声明后可在后续步骤引用,但不可在声明前引用。别名可用“Set x to someOtherValue”进行赋值。
5.2.1 抽象操作
为便于在规范多个部分中使用,部分算法(称为抽象操作)采用命名并参数化的函数形式书写,以便在其他算法中通过名称引用。抽象操作通常以函数调用形式引用,如 OperationName(arg1, arg2)。有些抽象操作作为类似类的规范抽象的多态分派方法对待,这类方法通常以 someValue.OperationName(arg1, arg2) 形式引用。
5.2.2 语法导向操作
语法导向操作是指以名称定义、由若干算法组成,并与 ECMAScript 某个文法中的一个或多个产生式关联的操作。具有多个备选定义的产生式通常为每个备选定义关联一个独立算法。若算法与某个文法产生式关联,则可将产生式备选中的终结符和非终结符视为算法参数进行引用。以此方式使用时,非终结符引用实际为解析源文本时匹配的具体备选定义。某个文法产生式或其派生的解析节点所匹配的源文本是指从第一个参与匹配的终结符开始到最后一个终结符结束的源文本片段。
当算法与产生式备选关联时,备选一般不带“[ ]”文法标注。这些标注仅影响备选的句法识别,对备选相关语义无影响。
语法导向操作通过解析节点和可选参数调用,具体调用方式见以下算法的 1、3 和 4 步骤:
- Let status be SyntaxDirectedOperation of SomeNonTerminal.
- Let someParseNode be the parse of some source text.
- Perform SyntaxDirectedOperation of someParseNode.
- Perform SyntaxDirectedOperation of someParseNode with argument "value".
除非另有说明,所有链式产生式都隐含定义了对该产生式左部非终结符可应用的所有操作的隐含定义。隐含定义即对链式产生式唯一右部非终结符以相同参数重复应用同一操作,返回结果。例如,假设某算法有如下步骤:“Return Evaluation of Block”且有如下产生式:
Block :
{
StatementList
}
但 Evaluation 操作未与该产生式关联算法,则此时 Evaluation 操作隐含如下关联:
运行时语义:Evaluation
Block :
{
StatementList
}
- Return Evaluation of StatementList.
5.2.3 运行时语义
指定运行时必须调用的语义的算法称为运行时语义。运行时语义通过抽象操作或语法导向操作定义。
5.2.3.1 Completion ( completionRecord )
The abstract operation Completion takes argument completionRecord (a Completion Record) and returns a Completion Record. It performs the following steps when called:
- Assert: completionRecord 是 Completion Record。
- Return completionRecord.
5.2.3.2 抛出异常
算法步骤如:
- Throw a TypeError exception.
与如下语句含义相同:
- Return ThrowCompletion(a newly created TypeError object).
5.2.3.3 ReturnIfAbrupt
算法步骤如:
- ReturnIfAbrupt(argument).
与如下语句含义相同:
- Assert: argument 是 Completion Record。
- 如果 argument 是异常完成,则返回 Completion(argument)。
- 否则,将 argument 设为 argument.[[Value]]。
算法步骤如:
- ReturnIfAbrupt(AbstractOperation()).
与如下语句含义相同:
- Let hygienicTemp be AbstractOperation().
- Assert: hygienicTemp 是 Completion Record。
- 如果 hygienicTemp 是异常完成,则返回 Completion(hygienicTemp)。
- 否则,将 hygienicTemp 设为 hygienicTemp.[[Value]]。
其中 hygienicTemp 仅在 ReturnIfAbrupt 相关步骤中可见且为临时变量。
算法步骤如:
- Let result be AbstractOperation(ReturnIfAbrupt(argument)).
与如下语句含义相同:
- Assert: argument 是 Completion Record。
- 如果 argument 是异常完成,则返回 Completion(argument)。
- 否则,将 argument 设为 argument.[[Value]]。
- Let result be AbstractOperation(argument)。
5.2.3.4 ReturnIfAbrupt 简记法
抽象操作和语法导向操作调用前加 ?
表示应对返回的 Completion Record 应用 ReturnIfAbrupt。例如:
- ? OperationName().
等价于:
- ReturnIfAbrupt(OperationName()).
类似地,方法调用风格:
- ? someValue.OperationName().
等价于:
- ReturnIfAbrupt(someValue.OperationName()).
类似地,前缀 !
表示后续抽象或语法导向操作的调用不会返回异常完成,结果应取 Completion Record 的 [[Value]] 字段作为操作的返回值。例如:
- Let val be ! OperationName().
等价于:
- Let val be OperationName()。
- Assert: val 是正常完成。
- Set val to val.[[Value]]。
运行时语义的语法导向操作会通过在操作调用前加 !
或 ?
使用此简记法:
- Perform ! SyntaxDirectedOperation of NonTerminal。
5.2.3.5 隐式正常完成
对于声明为返回 Completion Record 的抽象操作算法以及所有内建函数,其返回值会先传递给 NormalCompletion,再使用结果。该规则不适用于 Completion 算法内部或返回值明确标为 Completion Record 的步骤;包括:
如果通过其他方式从此类抽象操作返回 Completion Record,则属于编辑错误。例如,在这些抽象操作中,
- Return true.
与如下语句含义相同:
- Return NormalCompletion(true)。
或
- Let completion be NormalCompletion(true)。
- Return Completion(completion)。
或
- Return Completion Record { [[Type]]: normal, [[Value]]: true, [[Target]]: empty }。
注意,通过 ReturnIfAbrupt 展开,以下写法允许,因为在展开步骤中,异常情况直接返回 Completion,正常情况在解包后隐式应用 NormalCompletion。
- Return ? completion。
以下示例则属于编辑错误,因为返回 Completion Record 时未在该步骤标注。
- Let completion be NormalCompletion(true)。
- Return completion。
5.2.4 静态语义
上下文无关文法无法表达所有判断输入元素流是否能组成可求值的有效 ECMAScript Script 或 Module 的规则。在某些情况下需补充规则,可用 ECMAScript 算法约定或散文要求表达。这些规则总是与某个文法产生式关联,称为该产生式的静态语义。
静态语义规则有名称,通常用算法定义。命名静态语义规则与文法产生式关联,具有多个备选定义的产生式通常为每个备选和每个适用的命名静态语义规则定义独立算法。
一种特殊的静态语义规则是早期错误规则。早期错误规则定义了与特定文法产生式关联的早期错误条件(见 17 条款)。大多数早期错误规则的判断不会在规范算法中显式调用。符合规范的实现必须在首次求值 Script 或 Module 之前,验证用于解析该 Script 或 Module 的所有产生式的早期错误规则。如果有任何早期错误规则被违反,则该 Script 或 Module 无效且不可求值。
5.2.5 数学运算
规范涉及以下数值类型:
在规范语言中,不同数值类型通过下标后缀区分。下标 𝔽 表示 Numbers,下标 ℤ 表示 BigInts。无下标后缀的数值表示数学值。规范多数数值以十进制表示,也用 0x 加数字 0-9 或 A-F 表示十六进制。
一般来说,规范提及数值时,如“y 的长度”或“四个十六进制数字表示的整数”,未显式说明数值类型时,指的是数学值。指明 Number 或 BigInt 时会明确标注,如“表示代码点数量的 Number 值”或“表示某值的 BigInt 值”。
规范中的integer指数学上的整数,除非另有说明。integral Number指数学值为整数的有限 Number 值。
如 +、×、=、≥ 等数值运算符,具体操作取决于操作数类型。用于数学值时为常规数学运算,扩展数学值时为扩展实数运算(不定义不定型,规范中出现为编辑错误),用于 Number 时为 IEEE 754-2019 运算,BigInt 时为 BigInt 的数学值运算。混合类型操作数(如 Number 与数学值)不定义,规范中出现为编辑错误。
数学值与 Number 或 BigInt 间转换均为显式。数学值或扩展数学值 x 转 Number 表示为“x 的 Number 值”或 𝔽(x),见 6.1.6.1。整数 x 转 BigInt 表示为“x 的 BigInt 值”或 ℤ(x)。Number 或 BigInt x 转数学值表示为“x 的 数学值”或 ℝ(x)。+0𝔽 和 -0𝔽 的数学值为 0,非有限值的数学值不定义。x 的扩展数学值 对于有限值为数学值,+∞𝔽 和 -∞𝔽 分别为 +∞ 和 -∞,NaN 不定义。
数学函数 abs(x) 返回 x 的绝对值,即当 x < 0 时为 -x,否则为 x。
数学函数 min(x1, x2, … , xN) 取 x1 到 xN 中最小值,max(x1, x2, ..., xN) 取最大值,定义域和值域为扩展数学值。
记号“x 模 y”(y 必须为有限且非零)计算与 y 同号或为零的值 k,满足 abs(k) < abs(y) 且 x - k = q × y,其中 q 为整数。
“将 x 限制在 lower 与 upper 之间”(x 为扩展数学值,lower 和 upper 为满足 lower ≤ upper 的数学值)表示若 x < lower,则取 lower,若 x > upper,则取 upper,否则取 x。
数学函数 floor(x) 返回不大于 x 的最大整数(最接近 +∞)。
Note
数学函数 truncate(x) 通过向零舍入移除 x 的小数部分,当 x < 0 时为 -floor(-x),否则为 floor(x)。
数学函数 min、max、abs、floor 和 truncate 不用于 Numbers 和 BigInts,对非数学值参数使用这些方法属于编辑错误。
区间从下界 a 到上界 b,是同一数值类型的可能无限或空的数值集合。每个边界描述为闭或开,不可兼有。区间分为四种:
- 从 a(闭)到 b(闭),亦称闭区间,包含所有满足 a ≤ x ≤ b 的同类型值 x。
- 从 a(闭)到 b(开),包含所有满足 a ≤ x < b 的同类型值 x。
- 从 a(开)到 b(闭),包含所有满足 a < x ≤ b 的同类型值 x。
- 从 a(开)到 b(开),包含所有满足 a < x < b 的同类型值 x。
例如,1(闭)到 2(开)区间包含所有 1 到 2 之间的数学值,包括 1 不包括 2。定义区间时,-0𝔽 < +0𝔽,因此下界为 +0𝔽 的闭区间包含 +0𝔽 但不包含 -0𝔽。NaN 永不包含在区间内。
5.2.6 值记号
本规范中,ECMAScript 语言值用 粗体 显示,如 null、true 或 "hello"。这与 ECMAScript 源文本(如 Function.prototype.apply
或 let n = 42;
)区分开。
5.2.7 同一性
本规范中,规范值和 ECMAScript 语言值都可进行相等性比较。比较时,值分为两类。无同一性的值,若所有固有特性相同(如整数的大小或序列的长度)则彼此相等。无同一性值可通过完全描述其特性直接表现,无需先前引用。相比之下,有同一性的值是唯一的,仅与自身相等。有同一性的值除了拥有无同一性值的特性,还具有不可猜测、不可变、全局唯一的特性,称为同一性。对现有有同一性的值的引用不能仅通过描述其特性表现,同一性本身无法描述,必须显式传递。有同一性的值有些可变,可原地改变其特性(除了同一性),所有持有者都能观察到新特性。无同一性值永远不等于有同一性值。
在规范角度,“is”用于比较两个值是否相等,例如“If bool is true, then ...”;“contains”用于在列表中用相等性比较查找值,如“If list contains a Record r such that r.[[Foo]] is true, then ...”。规范值的规范同一性决定了这些比较结果,是规范中的公理。
ECMAScript 语言角度,语言值通过 SameValue 抽象操作及其递归调用比较相等性。这些比较算法决定 ECMAScript 语言值的语言同一性。
规范值中,无规范同一性的例子包括但不限于:数学值和扩展数学值;ECMAScript 源文本、代理对、指令序言等;UTF-16 码元;Unicode 码点;枚举;抽象操作(包括语法导向操作、宿主钩子等);有序对。有规范同一性的例子包括但不限于:各种记录(包括属性描述符、PrivateElements 等);解析节点;列表;集合与关系;抽象闭包;数据块;私有名称;执行上下文及上下文栈;代理标识符;WaiterList 记录。
对所有 ECMAScript 语言值,除由 Symbol.for 生成的 Symbol 外,规范同一性与语言同一性一致。无规范同一性且无语言同一性的 ECMAScript 语言值包括 undefined、null、Boolean、String、Number、BigInt。有规范同一性和语言同一性的 ECMAScript 语言值包括 Symbol(非 Symbol.for 生成)和 Object。由 Symbol.for 生成的 Symbol 有规范同一性但无语言同一性。