13 ECMAScript 语言:表达式

13.1 标识符

语法

IdentifierReference[Yield, Await] : Identifier [~Yield] yield [~Await] await BindingIdentifier[Yield, Await] : Identifier yield await LabelIdentifier[Yield, Await] : Identifier [~Yield] yield [~Await] await Identifier : IdentifierName but not ReservedWord Note

在文法中,yieldawait 被允许作为 BindingIdentifier, 并在下方通过静态语义禁止,以避免在如下情形中发生自动分号插入

let
await 0;

13.1.1 Static Semantics: 早期错误

BindingIdentifier : Identifier IdentifierReference : yield BindingIdentifier : yield LabelIdentifier : yield
  • 如果 IsStrict(this production) 为 true,则是语法错误。
IdentifierReference : await BindingIdentifier : await LabelIdentifier : await BindingIdentifier[Yield, Await] : yield
  • 如果该产生式具有一个 [Yield] 参数,则是语法错误。
BindingIdentifier[Yield, Await] : await
  • 如果该产生式具有一个 [Await] 参数,则是语法错误。
IdentifierReference[Yield, Await] : Identifier BindingIdentifier[Yield, Await] : Identifier LabelIdentifier[Yield, Await] : Identifier
  • 如果该产生式具有一个 [Yield] 参数,并且 IdentifierStringValue"yield",则是语法错误。
  • 如果该产生式具有一个 [Await] 参数,并且 IdentifierStringValue"await",则是语法错误。
Identifier : IdentifierName but not ReservedWord Note

IdentifierNameStringValue 会将 IdentifierName 中的任意 Unicode 转义序列规范化,因此不能使用这类转义来书写一个码点序列与某个 ReservedWord 相同的 Identifier

13.1.2 Static Semantics: StringValue

The syntax-directed operation StringValue takes no arguments and returns 一个 String. It is defined piecewise over the following productions:

IdentifierName :: IdentifierStart IdentifierName IdentifierPart
  1. idTextUnescapedIdentifierNameIdentifierCodePoints
  2. 返回 CodePointsToString(idTextUnescaped)。
IdentifierReference : yield BindingIdentifier : yield LabelIdentifier : yield
  1. 返回 "yield"
IdentifierReference : await BindingIdentifier : await LabelIdentifier : await
  1. 返回 "await"
Identifier : IdentifierName but not ReservedWord
  1. 返回 IdentifierNameStringValue
PrivateIdentifier :: # IdentifierName
  1. 返回 0x0023(NUMBER SIGN)与 IdentifierNameStringValue 的字符串串接结果。
ModuleExportName : StringLiteral
  1. 返回 StringLiteralSV

13.1.3 Runtime Semantics: 求值

IdentifierReference : Identifier
  1. 返回 ? ResolveBinding(StringValue of Identifier)。
IdentifierReference : yield
  1. 返回 ? ResolveBinding("yield")。
IdentifierReference : await
  1. 返回 ? ResolveBinding("await")。
Note 1

IdentifierReference 求值的结果总是一个 Reference 类型的值。

Note 2

非严格代码中,关键字 yield 可以被用作标识符。对该 IdentifierReference 的求值会像它是一个 Identifier 一样解析 yield 的绑定。早期错误限制确保这类求值只会出现在非严格代码中。

13.2 主表达式

语法

PrimaryExpression[Yield, Await] : this IdentifierReference[?Yield, ?Await] Literal ArrayLiteral[?Yield, ?Await] ObjectLiteral[?Yield, ?Await] FunctionExpression ClassExpression[?Yield, ?Await] GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral[?Yield, ?Await, ~Tagged] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[Yield, Await] : ( Expression[+In, ?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ) ( ) ( ... BindingIdentifier[?Yield, ?Await] ) ( ... BindingPattern[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingIdentifier[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingPattern[?Yield, ?Await] )

补充语法

在处理如下产生式的一个实例时
PrimaryExpression[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
CoverParenthesizedExpressionAndArrowParameterList 的解释会使用如下文法加以细化:

ParenthesizedExpression[Yield, Await] : ( Expression[+In, ?Yield, ?Await] )

13.2.1 this 关键字

13.2.1.1 Runtime Semantics: 求值

PrimaryExpression : this
  1. 返回 ? ResolveThisBinding()。

13.2.2 标识符引用

有关 IdentifierReference,见 13.1

13.2.3 字面量

语法

Literal : NullLiteral BooleanLiteral NumericLiteral StringLiteral

13.2.3.1 Runtime Semantics: 求值

Literal : NullLiteral
  1. 返回 null
Literal : BooleanLiteral
  1. 如果 BooleanLiteral 是记号 false,返回 false
  2. 如果 BooleanLiteral 是记号 true,返回 true
Literal : NumericLiteral
  1. 返回按 12.9.3 中定义的 NumericLiteralNumericValue
Literal : StringLiteral
  1. 返回按 12.9.4.2 中定义的 StringLiteralSV

13.2.4 数组初始化器

Note

ArrayLiteral 是一种描述 Array 初始化的表达式,它使用方括号括起来的 0 个或多个表达式的列表来表示,其中每个表达式代表一个数组元素。这些元素不必 是字面量;每次对该数组初始化器求值时,它们都会被求值。

数组元素可以在元素列表的开头、中间或结尾被省略。每当元素列表中的一个逗号 前面没有 AssignmentExpression(即,位于开头的逗号,或者位于另一个逗号 之后的逗号),这个缺失的数组元素就会对 Array 的长度作出贡献,并增加后续元 素的索引。被省略的数组元素不会被定义。如果一个元素在数组末尾被省略,该元素 不会对 Array 的长度作出贡献。

语法

ArrayLiteral[Yield, Await] : [ Elisionopt ] [ ElementList[?Yield, ?Await] ] [ ElementList[?Yield, ?Await] , Elisionopt ] ElementList[Yield, Await] : Elisionopt AssignmentExpression[+In, ?Yield, ?Await] Elisionopt SpreadElement[?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt AssignmentExpression[+In, ?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt SpreadElement[?Yield, ?Await] Elision : , Elision , SpreadElement[Yield, Await] : ... AssignmentExpression[+In, ?Yield, ?Await]

13.2.4.1 Runtime Semantics: ArrayAccumulation

The syntax-directed operation ArrayAccumulation takes arguments array (一个 Array) and nextIndex (一个整数) and returns 要么是一个正常完成,包含一个整数,要么是一个突然完成. It is defined piecewise over the following productions:

Elision : ,
  1. lennextIndex + 1。
  2. 执行 ? Set(array, "length", 𝔽(len), true)。
  3. NOTE: 如果 len 超过 232 - 1,上一步会抛出异常。
  4. 返回 len
Elision : Elision ,
  1. 返回 ? 对 Elision 执行 ArrayAccumulation,并以 array 和 (nextIndex + 1) 为参数。
ElementList : Elisionopt AssignmentExpression
  1. 如果 Elision 存在,那么
    1. nextIndex 设为 ? 对 Elision 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  2. initResult 为 ? 对 AssignmentExpression 求值。
  3. initValue 为 ? GetValue(initResult)。
  4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue)。
  5. 返回 nextIndex + 1。
ElementList : Elisionopt SpreadElement
  1. 如果 Elision 存在,那么
    1. nextIndex 设为 ? 对 Elision 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  2. 返回 ? 对 SpreadElement 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
ElementList : ElementList , Elisionopt AssignmentExpression
  1. nextIndex 设为 ? 对已派生的 ElementList 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  2. 如果 Elision 存在,那么
    1. nextIndex 设为 ? 对 Elision 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  3. initResult 为 ? 对 AssignmentExpression 求值。
  4. initValue 为 ? GetValue(initResult)。
  5. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue)。
  6. 返回 nextIndex + 1。
ElementList : ElementList , Elisionopt SpreadElement
  1. nextIndex 设为 ? 对已派生的 ElementList 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  2. 如果 Elision 存在,那么
    1. nextIndex 设为 ? 对 Elision 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  3. 返回 ? 对 SpreadElement 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
SpreadElement : ... AssignmentExpression
  1. spreadRef 为 ? 对 AssignmentExpression 求值。
  2. spreadObj 为 ? GetValue(spreadRef)。
  3. iteratorRecord 为 ? GetIterator(spreadObj, sync)。
  4. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 nextIndex
    3. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), next)。
    4. nextIndex 设为 nextIndex + 1。
Note

使用 CreateDataPropertyOrThrow 是为了确保即使标准内建 Array 原型对象 已经被修改得无法通过 [[Set]] 创建新的自有属性,数组上仍然会定义自有属性。

13.2.4.2 Runtime Semantics: 求值

ArrayLiteral : [ Elisionopt ]
  1. array 为 ! ArrayCreate(0)。
  2. 如果 Elision 存在,那么
    1. 执行 ? 对 Elision 执行 ArrayAccumulation,并以 array 和 0 为参数。
  3. 返回 array
ArrayLiteral : [ ElementList ]
  1. array 为 ! ArrayCreate(0)。
  2. 执行 ? 对 ElementList 执行 ArrayAccumulation,并以 array 和 0 为参数。
  3. 返回 array
ArrayLiteral : [ ElementList , Elisionopt ]
  1. array 为 ! ArrayCreate(0)。
  2. nextIndex 为 ? 对 ElementList 执行 ArrayAccumulation,并以 array 和 0 为参数。
  3. 如果 Elision 存在,那么
    1. 执行 ? 对 Elision 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  4. 返回 array

13.2.5 对象初始化器

Note 1

对象初始化器是一种描述 Object 初始化的表达式,其书写形式类似字面量。它 是一个由 0 个或多个属性键及其相关联值所组成的列表,且被花括号包围。这些值 不必是字面量;每次对该对象初始化器求值时,它们都会被求值。

语法

ObjectLiteral[Yield, Await] : { } { PropertyDefinitionList[?Yield, ?Await] } { PropertyDefinitionList[?Yield, ?Await] , } PropertyDefinitionList[Yield, Await] : PropertyDefinition[?Yield, ?Await] PropertyDefinitionList[?Yield, ?Await] , PropertyDefinition[?Yield, ?Await] PropertyDefinition[Yield, Await] : IdentifierReference[?Yield, ?Await] CoverInitializedName[?Yield, ?Await] PropertyName[?Yield, ?Await] : AssignmentExpression[+In, ?Yield, ?Await] MethodDefinition[?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] PropertyName[Yield, Await] : LiteralPropertyName ComputedPropertyName[?Yield, ?Await] LiteralPropertyName : IdentifierName StringLiteral NumericLiteral ComputedPropertyName[Yield, Await] : [ AssignmentExpression[+In, ?Yield, ?Await] ] CoverInitializedName[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] Initializer[In, Yield, Await] : = AssignmentExpression[?In, ?Yield, ?Await] Note 2

MethodDefinition 定义于 15.4

Note 3

在某些上下文中,ObjectLiteral 被用作更受限的次级文法的覆盖文法。 CoverInitializedName 产生式对于完整覆盖这些次级文法是必要的。然而, 使用这个产生式会在那些期望出现实际 ObjectLiteral 的普通上下文中导致一 个早期语法错误。

13.2.5.1 Static Semantics: 早期错误

PropertyDefinition : MethodDefinition

ObjectLiteral 产生式除了描述实际对象初始化器之外,还被用作 ObjectAssignmentPattern覆盖文法,并且可能会被识别为 CoverParenthesizedExpressionAndArrowParameterList 的一部分。当 ObjectLiteral 出现在要求 ObjectAssignmentPattern 的上下文中时,下 述早期错误规则不会被应用。此外,在初始解析 CoverParenthesizedExpressionAndArrowParameterListCoverCallExpressionAndAsyncArrowHead 时,也不会应用这些规则。

PropertyDefinition : CoverInitializedName
  • 如果有任何源文本被该产生式匹配,则是语法错误。
Note 1

该产生式存在是为了让 ObjectLiteral 能作为 ObjectAssignmentPattern覆盖文法。它不能出现在实际对象初始化器中。

ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , } Note 2

PropertyNameList 返回的列表不包括使用 ComputedPropertyName 定义的属性名

13.2.5.2 Static Semantics: IsComputedPropertyKey

The syntax-directed operation IsComputedPropertyKey takes no arguments and returns 一个 Boolean. It is defined piecewise over the following productions:

PropertyName : LiteralPropertyName
  1. 返回 false
PropertyName : ComputedPropertyName
  1. 返回 true

13.2.5.3 Static Semantics: PropertyDefinitionNodes

The syntax-directed operation PropertyDefinitionNodes takes no arguments and returns 一个 Parse Node 列表. It is defined piecewise over the following productions:

ObjectLiteral : { }
  1. 返回一个新的空列表。
PropertyDefinitionList : PropertyDefinition
  1. 返回 « PropertyDefinition »。
PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. head 为已派生的 PropertyDefinitionListPropertyDefinitionNodes
  2. 返回 head 与 « PropertyDefinition » 的列表串接。

13.2.5.4 Static Semantics: PropertyNameList

The syntax-directed operation PropertyNameList takes no arguments and returns 一个 String 列表. It is defined piecewise over the following productions:

PropertyDefinitionList : PropertyDefinition
  1. propNamePropertyDefinitionPropName
  2. 如果 propNameempty,返回一个新的空列表。
  3. 返回 « propName »。
PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. listPropertyDefinitionListPropertyNameList
  2. propNamePropertyDefinitionPropName
  3. 如果 propNameempty,返回 list
  4. 返回 list 与 « propName » 的列表串接。

13.2.5.5 Runtime Semantics: 求值

ObjectLiteral : { }
  1. 返回 OrdinaryObjectCreate(%Object.prototype%)。
ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , }
  1. objOrdinaryObjectCreate(%Object.prototype%)。
  2. 执行 ? 对 PropertyDefinitionList 执行 PropertyDefinitionEvaluation,并以 obj 为参数。
  3. 返回 obj
LiteralPropertyName : IdentifierName
  1. 返回 IdentifierNameStringValue
LiteralPropertyName : StringLiteral
  1. 返回 StringLiteralSV
LiteralPropertyName : NumericLiteral
  1. nbrNumericLiteralNumericValue
  2. 返回 ! ToString(nbr)。
ComputedPropertyName : [ AssignmentExpression ]
  1. exprValue 为 ? 对 AssignmentExpression 求值。
  2. propName 为 ? GetValue(exprValue)。
  3. 返回 ? ToPropertyKey(propName)。

13.2.5.6 Runtime Semantics: PropertyDefinitionEvaluation

The syntax-directed operation PropertyDefinitionEvaluation takes argument object (一个 Object) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成. It is defined piecewise over the following productions:

PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. 执行 ? 对 PropertyDefinitionList 执行 PropertyDefinitionEvaluation,并以 object 为参数。
  2. 执行 ? 对 PropertyDefinition 执行 PropertyDefinitionEvaluation,并以 object 为参数。
  3. 返回 unused
PropertyDefinition : ... AssignmentExpression
  1. exprValue 为 ? 对 AssignmentExpression 求值。
  2. fromValue 为 ? GetValue(exprValue)。
  3. excludedNames 为一个新的空列表。
  4. 执行 ? CopyDataProperties(object, fromValue, excludedNames)。
  5. 返回 unused
PropertyDefinition : IdentifierReference
  1. propNameIdentifierReferenceStringValue
  2. exprValue 为 ? 对 IdentifierReference 求值。
  3. propValue 为 ? GetValue(exprValue)。
  4. 断言:object 是一个普通的、可扩展的对象,并且不具有不可配置属性。
  5. 执行 ! CreateDataPropertyOrThrow(object, propName, propValue)。
  6. 返回 unused
PropertyDefinition : PropertyName : AssignmentExpression
  1. propertyKey 为 ? 对 PropertyName 求值。
  2. 如果该 PropertyDefinition 包含于一个正为 ParseJSON 求值的 Script 中(见 ParseJSON 的步骤 6),那么
    1. isProtoSetterfalse
  3. 否则如果 propertyKey"__proto__",并且 PropertyNameIsComputedPropertyKeyfalse,那么
    1. isProtoSettertrue
  4. 否则,
    1. isProtoSetterfalse
  5. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 trueisProtoSetterfalse,那么
    1. propValue 为 ? 对 AssignmentExpression 执行 NamedEvaluation,并以 propertyKey 为参数。
  6. 否则,
    1. exprValueRef 为 ? 对 AssignmentExpression 求值。
    2. propValue 为 ? GetValue(exprValueRef)。
  7. 如果 isProtoSettertrue,那么
    1. 如果 propValue 是一个 Object 或 propValuenull,那么
      1. 执行 ! object.[[SetPrototypeOf]](propValue)
    2. 返回 unused
  8. 断言:object 是一个普通的、可扩展的对象,并且不具有不可配置属性。
  9. 执行 ! CreateDataPropertyOrThrow(object, propertyKey, propValue)。
  10. 返回 unused
PropertyDefinition : MethodDefinition
  1. 执行 ? 对 MethodDefinition 执行 MethodDefinitionEvaluation,并以 objecttrue 为参数。
  2. 返回 unused

13.2.6 函数定义表达式

有关 PrimaryExpression : FunctionExpression , 见 15.2

有关 PrimaryExpression : GeneratorExpression , 见 15.5

有关 PrimaryExpression : ClassExpression , 见 15.7

有关 PrimaryExpression : AsyncFunctionExpression , 见 15.8

有关 PrimaryExpression : AsyncGeneratorExpression , 见 15.6

13.2.7 正则表达式字面量

语法

12.9.5

13.2.7.1 Static Semantics: 早期错误

PrimaryExpression : RegularExpressionLiteral

13.2.7.2 Static Semantics: IsValidRegularExpressionLiteral ( literal )

The abstract operation IsValidRegularExpressionLiteral takes argument literal (一个 RegularExpressionLiteral Parse Node) and returns 一个 Boolean. 它判定其参数是否为一个有效的正则表达式字面量。 It performs the following steps when called:

  1. flagsliteralFlagText
  2. 如果 flags 包含除 dgimsuvy 之外的任何码点,返回 false
  3. 如果 flags 中有任何码点出现多于一次,返回 false
  4. 如果 flags 包含 u,令 utrue;否则令 ufalse
  5. 如果 flags 包含 v,令 vtrue;否则令 vfalse
  6. patternTextliteralBodyText
  7. 如果 ufalsevfalse,那么
    1. stringValueCodePointsToString(patternText)。
    2. patternText 设为如下得到的码点序列:把 stringValue 的每个 16 位元素解释为一个 Unicode BMP 码点。不会对这些元素应用 UTF-16 解码。
  8. parseResultParsePattern(patternText, u, v)。
  9. 如果 parseResult 是一个 Parse Node,返回 true
  10. 返回 false

13.2.7.3 Runtime Semantics: 求值

PrimaryExpression : RegularExpressionLiteral
  1. patternCodePointsToString(BodyText of RegularExpressionLiteral)。
  2. flagsCodePointsToString(FlagText of RegularExpressionLiteral)。
  3. 返回 ! RegExpCreate(pattern, flags)。

13.2.8 模板字面量

语法

TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate SubstitutionTemplate[?Yield, ?Await, ?Tagged] SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await]

13.2.8.1 Static Semantics: 早期错误

TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate TemplateLiteral[Yield, Await, Tagged] : SubstitutionTemplate[?Yield, ?Await, ?Tagged] SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await]

13.2.8.2 Static Semantics: TemplateStrings

The syntax-directed operation TemplateStrings takes argument raw (一个 Boolean) and returns 一个由 String 或 undefined 构成的列表. It is defined piecewise over the following productions:

TemplateLiteral : NoSubstitutionTemplate
  1. 返回 « TemplateString(NoSubstitutionTemplate, raw) »。
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. head 为 « TemplateString(TemplateHead, raw) »。
  2. tail 为以 raw 为参数调用 TemplateSpansTemplateStrings
  3. 返回 headtail 的列表串接。
TemplateSpans : TemplateTail
  1. 返回 « TemplateString(TemplateTail, raw) »。
TemplateSpans : TemplateMiddleList TemplateTail
  1. middle 为以 raw 为参数调用 TemplateMiddleListTemplateStrings
  2. tail 为 « TemplateString(TemplateTail, raw) »。
  3. 返回 middletail 的列表串接。
TemplateMiddleList : TemplateMiddle Expression
  1. 返回 « TemplateString(TemplateMiddle, raw) »。
TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. front 为以 raw 为参数调用 TemplateMiddleListTemplateStrings
  2. last 为 « TemplateString(TemplateMiddle, raw) »。
  3. 返回 frontlast 的列表串接。

13.2.8.3 Static Semantics: TemplateString ( templateToken, raw )

The abstract operation TemplateString takes arguments templateToken (一个 NoSubstitutionTemplate Parse Node、一个 TemplateHead Parse Node、一个 TemplateMiddle Parse Node 或一个 TemplateTail Parse Node) and raw (一个 Boolean) and returns 一个 String 或 undefined. It performs the following steps when called:

  1. 如果 rawtrue,那么
    1. stringtemplateTokenTRV
  2. 否则,
    1. stringtemplateTokenTV
  3. 返回 string
Note

如果 rawfalsetemplateToken 包含一个 NotEscapeSequence,则该操作返回 undefined。在所有其他情况下, 它返回一个 String。

13.2.8.4 GetTemplateObject ( templateLiteral )

The abstract operation GetTemplateObject takes argument templateLiteral (一个 Parse Node) and returns 一个 Array. It performs the following steps when called:

  1. realm当前 Realm Record
  2. templateRegistryrealm.[[TemplateMap]]
  3. 对于 templateRegistry 中的每个元素 e,执行
    1. 如果 e.[[Site]]templateLiteral 是同一个 Parse Node,那么
      1. 返回 e.[[Array]]
  4. rawStrings 为以 true 为参数调用 templateLiteralTemplateStrings
  5. 断言:rawStrings 是一个 String 列表。
  6. cookedStrings 为以 false 为参数调用 templateLiteralTemplateStrings
  7. count 为列表 cookedStrings 中元素的个数。
  8. 断言:count ≤ 232 - 1。
  9. template 为 ! ArrayCreate(count)。
  10. rawObj 为 ! ArrayCreate(count)。
  11. index 为 0。
  12. 重复,当 index < count 时,
    1. propertyKey 为 ! ToString(𝔽(index))。
    2. cookedValuecookedStrings[index]。
    3. 执行 ! DefinePropertyOrThrow(template, propertyKey, PropertyDescriptor { [[Value]]: cookedValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false })。
    4. rawValue 为 String 值 rawStrings[index]。
    5. 执行 ! DefinePropertyOrThrow(rawObj, propertyKey, PropertyDescriptor { [[Value]]: rawValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false })。
    6. index 设为 index + 1。
  13. 执行 ! SetIntegrityLevel(rawObj, frozen)。
  14. 执行 ! DefinePropertyOrThrow(template, "raw", PropertyDescriptor { [[Value]]: rawObj, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false })。
  15. 执行 ! SetIntegrityLevel(template, frozen)。
  16. Record { [[Site]]: templateLiteral, [[Array]]: template } 追加到 realm.[[TemplateMap]]
  17. 返回 template
Note 1

模板对象的创建不可能导致一个突然完成。

Note 2

一个 realm 的程序代码中的每个 TemplateLiteral 都关联着一个唯一的模 板对象,该对象用于带标签模板的求值 (13.2.8.6)。 模板对象是被冻结的,并且每次对某个特定带标签模板求值时都会使用同一个模板对 象。模板对象是在首次对该 TemplateLiteral 求值时惰性创建,还是在首次求值 之前急切创建,是一个实现选择,ECMAScript 代码无法观察到。

Note 3

本规范未来版本可能会定义模板对象的额外不可枚举属性。

13.2.8.5 Runtime Semantics: SubstitutionEvaluation

The syntax-directed operation SubstitutionEvaluation takes no arguments and returns 要么是一个正常完成,包含一个 ECMAScript 语言值列表,要么是一个突然完成. It is defined piecewise over the following productions:

TemplateSpans : TemplateTail
  1. 返回一个新的空列表。
TemplateSpans : TemplateMiddleList TemplateTail
  1. 返回 ? 对 TemplateMiddleList 执行 SubstitutionEvaluation
TemplateMiddleList : TemplateMiddle Expression
  1. subRef 为 ? 对 Expression 求值。
  2. sub 为 ? GetValue(subRef)。
  3. 返回 « sub »。
TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. preceding 为 ? 对 TemplateMiddleList 执行 SubstitutionEvaluation
  2. nextRef 为 ? 对 Expression 求值。
  3. next 为 ? GetValue(nextRef)。
  4. 返回 preceding 与 « next » 的列表串接。

13.2.8.6 Runtime Semantics: 求值

TemplateLiteral : NoSubstitutionTemplate
  1. 返回按 12.9.6 中定义的 NoSubstitutionTemplateTV
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. head 为按 12.9.6 中定义的 TemplateHeadTV
  2. subRef 为 ? 对 Expression 求值。
  3. sub 为 ? GetValue(subRef)。
  4. middle 为 ? ToString(sub)。
  5. tail 为 ? 对 TemplateSpans 求值。
  6. 返回 headmiddletail 的字符串串接结果。
Note 1

应用于 Expression 值的字符串转换语义类似 String.prototype.concat, 而不是 + 运算符。

TemplateSpans : TemplateTail
  1. 返回按 12.9.6 中定义的 TemplateTailTV
TemplateSpans : TemplateMiddleList TemplateTail
  1. head 为 ? 对 TemplateMiddleList 求值。
  2. tail 为按 12.9.6 中定义的 TemplateTailTV
  3. 返回 headtail 的字符串串接结果。
TemplateMiddleList : TemplateMiddle Expression
  1. head 为按 12.9.6 中定义的 TemplateMiddleTV
  2. subRef 为 ? 对 Expression 求值。
  3. sub 为 ? GetValue(subRef)。
  4. middle 为 ? ToString(sub)。
  5. 返回 headmiddle 的字符串串接结果。
Note 2

应用于 Expression 值的字符串转换语义类似 String.prototype.concat, 而不是 + 运算符。

TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. rest 为 ? 对 TemplateMiddleList 求值。
  2. middle 为按 12.9.6 中定义的 TemplateMiddleTV
  3. subRef 为 ? 对 Expression 求值。
  4. sub 为 ? GetValue(subRef)。
  5. last 为 ? ToString(sub)。
  6. 返回 restmiddlelast 的字符串串接结果。
Note 3

应用于 Expression 值的字符串转换语义类似 String.prototype.concat, 而不是 + 运算符。

13.2.9 分组运算符

13.2.9.1 Static Semantics: 早期错误

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList

13.2.9.2 Runtime Semantics: 求值

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. expr 为被 CoverParenthesizedExpressionAndArrowParameterList覆盖ParenthesizedExpression
  2. 返回 ? 对 expr 求值。
ParenthesizedExpression : ( Expression )
  1. 返回 ? 对 Expression 求值。该结果可能是 Reference 类型。
Note

该算法不会对 Expression 的求值结果应用 GetValue。其主要动机在于使 得 deletetypeof 这样的运算符可以应用于带括号的表达式。

13.3 左侧表达式

语法

MemberExpression[Yield, Await] : PrimaryExpression[?Yield, ?Await] MemberExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] MemberExpression[?Yield, ?Await] . IdentifierName MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] SuperProperty[?Yield, ?Await] MetaProperty new MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] MemberExpression[?Yield, ?Await] . PrivateIdentifier SuperProperty[Yield, Await] : super [ Expression[+In, ?Yield, ?Await] ] super . IdentifierName MetaProperty : NewTarget ImportMeta NewTarget : new . target ImportMeta : import . meta NewExpression[Yield, Await] : MemberExpression[?Yield, ?Await] new NewExpression[?Yield, ?Await] CallExpression[Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] SuperCall[?Yield, ?Await] ImportCall[?Yield, ?Await] CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] CallExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] CallExpression[?Yield, ?Await] . IdentifierName CallExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] CallExpression[?Yield, ?Await] . PrivateIdentifier SuperCall[Yield, Await] : super Arguments[?Yield, ?Await] ImportCall[Yield, Await] : import ( AssignmentExpression[+In, ?Yield, ?Await] ,opt ) import ( AssignmentExpression[+In, ?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ,opt ) Arguments[Yield, Await] : ( ) ( ArgumentList[?Yield, ?Await] ) ( ArgumentList[?Yield, ?Await] , ) ArgumentList[Yield, Await] : AssignmentExpression[+In, ?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , ... AssignmentExpression[+In, ?Yield, ?Await] OptionalExpression[Yield, Await] : MemberExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalChain[Yield, Await] : ?. Arguments[?Yield, ?Await] ?. [ Expression[+In, ?Yield, ?Await] ] ?. IdentifierName ?. TemplateLiteral[?Yield, ?Await, +Tagged] ?. PrivateIdentifier OptionalChain[?Yield, ?Await] Arguments[?Yield, ?Await] OptionalChain[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] OptionalChain[?Yield, ?Await] . IdentifierName OptionalChain[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] OptionalChain[?Yield, ?Await] . PrivateIdentifier LeftHandSideExpression[Yield, Await] : NewExpression[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalExpression[?Yield, ?Await]

补充语法

在处理如下产生式的一个实例时
CallExpression : CoverCallExpressionAndAsyncArrowHead
CoverCallExpressionAndAsyncArrowHead 的解释会使用如下文法加以细化:

CallMemberExpression[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

13.3.1 静态语义

13.3.1.1 Static Semantics: 早期错误

OptionalChain : ?. TemplateLiteral OptionalChain TemplateLiteral
  • 如果有任何源文本被该产生式匹配,则是语法错误。
Note

该产生式存在是为了防止自动分号插入规则 (12.10) 被应用到如下代码:

a?.b
`c`

否则它会被解释为两条有效语句。其目的是与不使用可选链的类似代码保持一 致:

a.b
`c`

后者是一条有效语句,并且不会应用自动分号插入。

ImportMeta : import . meta

13.3.2 属性访问器

Note

属性通过名称进行访问,使用点记法:

或方括号记法:

点记法可由如下语法转换解释:

其行为与下式完全相同

MemberExpression [ <identifier-name-string> ]

类似地

其行为与下式完全相同

CallExpression [ <identifier-name-string> ]

其中 <identifier-name-string> 是 IdentifierNameStringValue

13.3.2.1 Runtime Semantics: 求值

MemberExpression : MemberExpression [ Expression ]
  1. baseReference 为 ? 对 MemberExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. strictIsStrict(this MemberExpression)。
  4. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
MemberExpression : MemberExpression . IdentifierName
  1. baseReference 为 ? 对 MemberExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. strictIsStrict(this MemberExpression)。
  4. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
MemberExpression : MemberExpression . PrivateIdentifier
  1. baseReference 为 ? 对 MemberExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. fieldNameStringPrivateIdentifierStringValue
  4. 返回 MakePrivateReference(baseValue, fieldNameString)。
CallExpression : CallExpression [ Expression ]
  1. baseReference 为 ? 对 CallExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. strictIsStrict(this CallExpression)。
  4. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
CallExpression : CallExpression . IdentifierName
  1. baseReference 为 ? 对 CallExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. strictIsStrict(this CallExpression)。
  4. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
CallExpression : CallExpression . PrivateIdentifier
  1. baseReference 为 ? 对 CallExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. fieldNameStringPrivateIdentifierStringValue
  4. 返回 MakePrivateReference(baseValue, fieldNameString)。

13.3.3 EvaluatePropertyAccessWithExpressionKey ( baseValue, expression, strict )

The abstract operation EvaluatePropertyAccessWithExpressionKey takes arguments baseValue (一个 ECMAScript 语言值), expression (一个 Expression Parse Node), and strict (一个 Boolean) and returns 要么是一个正常完成,包含一个 Reference Record,要么是一个突然完成. It performs the following steps when called:

  1. propertyNameReference 为 ? 对 expression 求值。
  2. propertyNameValue 为 ? GetValue(propertyNameReference)。
  3. NOTE: 在大多数情况下,ToPropertyKey 会在此步骤之后立即作用于 propertyNameValue。但是,在 a[b] = c 的情形下,它要等到对 c 求值之后才会执行。
  4. 返回 Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyNameValue, [[Strict]]: strict, [[ThisValue]]: empty }。

13.3.4 EvaluatePropertyAccessWithIdentifierKey ( baseValue, identifierName, strict )

The abstract operation EvaluatePropertyAccessWithIdentifierKey takes arguments baseValue (一个 ECMAScript 语言值), identifierName (一个 IdentifierName Parse Node), and strict (一个 Boolean) and returns 一个 Reference Record. It performs the following steps when called:

  1. propertyNameStringidentifierNameStringValue
  2. 返回 Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyNameString, [[Strict]]: strict, [[ThisValue]]: empty }。

13.3.5 new 运算符

13.3.5.1 Runtime Semantics: 求值

NewExpression : new NewExpression
  1. 返回 ? EvaluateNew(NewExpression, empty)。
MemberExpression : new MemberExpression Arguments
  1. 返回 ? EvaluateNew(MemberExpression, Arguments)。

13.3.5.1.1 EvaluateNew ( constructExpr, arguments )

The abstract operation EvaluateNew takes arguments constructExpr (a NewExpression Parse Node or a MemberExpression Parse Node) and arguments (empty or an Arguments Parse Node) and returns either a normal completion containing an Object or an abrupt completion. It performs the following steps when called:

  1. ref 为 ? 对 constructExpr 求值。
  2. constructor 为 ? GetValue(ref)。
  3. 如果 argumentsempty,那么
    1. argList 为一个新的空列表。
  4. 否则,
    1. argList 为 ? 对 arguments 执行 ArgumentListEvaluation
  5. 如果 IsConstructor(constructor) 为 false,抛出一个 TypeError 异常。
  6. 返回 ? Construct(constructor, argList)。

13.3.6 函数调用

13.3.6.1 Runtime Semantics: 求值

CallExpression : CoverCallExpressionAndAsyncArrowHead
  1. expr 为被 CoverCallExpressionAndAsyncArrowHead 覆盖CallMemberExpression
  2. memberExprexprMemberExpression
  3. argumentsexprArguments
  4. ref 为 ? 对 memberExpr 求值。
  5. func 为 ? GetValue(ref)。
  6. 如果 ref 是一个 Reference RecordIsPropertyReference(ref) 为 false,并且 ref.[[ReferencedName]]"eval",那么
    1. 如果 SameValue(func, %eval%) 为 true,那么
      1. argList 为 ? 对 arguments 执行 ArgumentListEvaluation
      2. 如果 argList 不含任何元素,返回 undefined
      3. evalArgargList 的第一个元素。
      4. 如果 IsStrict(this CallExpression) 为 true,令 strictCallertrue;否则令 strictCallerfalse
      5. 返回 ? PerformEval(evalArg, strictCaller, true)。
  7. thisCall 为该 CallExpression
  8. tailCallIsInTailPosition(thisCall)。
  9. 返回 ? EvaluateCall(func, ref, arguments, tailCall)。

执行步骤 6.a.vCallExpression 求值称为一个 直接 eval

CallExpression : CallExpression Arguments
  1. ref 为 ? 对 CallExpression 求值。
  2. func 为 ? GetValue(ref)。
  3. thisCall 为该 CallExpression
  4. tailCallIsInTailPosition(thisCall)。
  5. 返回 ? EvaluateCall(func, ref, Arguments, tailCall)。

13.3.6.2 EvaluateCall ( func, ref, arguments, tailPosition )

The abstract operation EvaluateCall takes arguments func (一个 ECMAScript 语言值), ref (一个 ECMAScript 语言值或一个 Reference Record), arguments (一个 Parse Node), and tailPosition (一个 Boolean) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个突然完成. It performs the following steps when called:

  1. 如果 ref 是一个 Reference Record,那么
    1. 如果 IsPropertyReference(ref) 为 true,那么
      1. thisValueGetThisValue(ref)。
    2. 否则,
      1. refEnvref.[[Base]]
      2. 断言:refEnv 是一个 Environment Record
      3. thisValuerefEnv.WithBaseObject()。
  2. 否则,
    1. thisValueundefined
  3. argList 为 ? 对 arguments 执行 ArgumentListEvaluation
  4. 如果 func 不是一个 Object,抛出一个 TypeError 异常。
  5. 如果 IsCallable(func) 为 false,抛出一个 TypeError 异常。
  6. 如果 tailPositiontrue,执行 PrepareForTailCall()。
  7. 返回 ? Call(func, thisValue, argList)。

13.3.7 super 关键字

13.3.7.1 Runtime Semantics: 求值

SuperProperty : super [ Expression ]
  1. envGetThisEnvironment()。
  2. actualThis 为 ? env.GetThisBinding()。
  3. propertyNameReference 为 ? 对 Expression 求值。
  4. propertyNameValue 为 ? GetValue(propertyNameReference)。
  5. strictIsStrict(this SuperProperty)。
  6. NOTE: 在大多数情况下,ToPropertyKey 会在此步骤之后立即作用于 propertyNameValue。但是,在 super[b] = c 的情形下,它要等到对 c 求值之后才会执行。
  7. 返回 MakeSuperPropertyReference(actualThis, propertyNameValue, strict)。
SuperProperty : super . IdentifierName
  1. envGetThisEnvironment()。
  2. actualThis 为 ? env.GetThisBinding()。
  3. propertyKeyIdentifierNameStringValue
  4. strictIsStrict(this SuperProperty)。
  5. 返回 MakeSuperPropertyReference(actualThis, propertyKey, strict)。
SuperCall : super Arguments
  1. newTargetGetNewTarget()。
  2. 断言:newTarget 是一个构造器
  3. superConstructorGetSuperConstructor()。
  4. argList 为 ? 对 Arguments 执行 ArgumentListEvaluation
  5. 如果 IsConstructor(superConstructor) 为 false,抛出一个 TypeError 异常。
  6. result 为 ? Construct(superConstructor, argList, newTarget)。
  7. thisERGetThisEnvironment()。
  8. 断言:thisER 是一个 Function Environment Record
  9. 执行 ? BindThisValue(thisER, result)。
  10. funcObjthisER.[[FunctionObject]]
  11. 断言:funcObj 是一个 ECMAScript 函数对象
  12. 执行 ? InitializeInstanceElements(result, funcObj)。
  13. 返回 result

13.3.7.2 GetSuperConstructor ( )

The abstract operation GetSuperConstructor takes no arguments and returns an Object or null. It performs the following steps when called:

  1. envRecGetThisEnvironment()。
  2. 断言:envRec 是一个 Function Environment Record
  3. activeFunctionenvRec.[[FunctionObject]]
  4. 断言:activeFunction 是一个 ECMAScript 函数对象
  5. superConstructor 为 ! activeFunction.[[GetPrototypeOf]]()。
  6. 返回 superConstructor

13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict )

The abstract operation MakeSuperPropertyReference takes arguments actualThis (一个 ECMAScript 语言值), propertyKey (一个 ECMAScript 语言值), and strict (一个 Boolean) and returns 一个 Super Reference Record. It performs the following steps when called:

  1. envGetThisEnvironment()。
  2. 断言:env.HasSuperBinding() 为 true
  3. 断言:env 是一个 Function Environment Record
  4. baseValueGetSuperBase(env)。
  5. 返回 Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: actualThis }。

13.3.8 实参列表

Note

对实参列表求值会产生一个值列表。

13.3.8.1 Runtime Semantics: ArgumentListEvaluation

The syntax-directed operation ArgumentListEvaluation takes no arguments and returns 要么是一个正常完成,包含一个 ECMAScript 语言值列表,要么是一个突然完成. It is defined piecewise over the following productions:

Arguments : ( )
  1. 返回一个新的空列表。
ArgumentList : AssignmentExpression
  1. ref 为 ? 对 AssignmentExpression 求值。
  2. arg 为 ? GetValue(ref)。
  3. 返回 « arg »。
ArgumentList : ... AssignmentExpression
  1. list 为一个新的空列表。
  2. spreadRef 为 ? 对 AssignmentExpression 求值。
  3. spreadObj 为 ? GetValue(spreadRef)。
  4. iteratorRecord 为 ? GetIterator(spreadObj, sync)。
  5. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 list
    3. next 追加到 list
ArgumentList : ArgumentList , AssignmentExpression
  1. precedingArgs 为 ? 对 ArgumentList 执行 ArgumentListEvaluation
  2. ref 为 ? 对 AssignmentExpression 求值。
  3. arg 为 ? GetValue(ref)。
  4. 返回 precedingArgs 与 « arg » 的列表串接。
ArgumentList : ArgumentList , ... AssignmentExpression
  1. precedingArgs 为 ? 对 ArgumentList 执行 ArgumentListEvaluation
  2. spreadRef 为 ? 对 AssignmentExpression 求值。
  3. iteratorRecord 为 ? GetIterator(? GetValue(spreadRef), sync)。
  4. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 precedingArgs
    3. next 追加到 precedingArgs
TemplateLiteral : NoSubstitutionTemplate
  1. templateLiteral 为该 TemplateLiteral
  2. siteObjGetTemplateObject(templateLiteral)。
  3. 返回 « siteObj »。
TemplateLiteral : SubstitutionTemplate
  1. templateLiteral 为该 TemplateLiteral
  2. siteObjGetTemplateObject(templateLiteral)。
  3. remaining 为 ? 对 SubstitutionTemplate 执行 ArgumentListEvaluation
  4. 返回 « siteObj » 与 remaining 的列表串接。
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. firstSubRef 为 ? 对 Expression 求值。
  2. firstSub 为 ? GetValue(firstSubRef)。
  3. restSub 为 ? 对 TemplateSpans 执行 SubstitutionEvaluation
  4. 断言:restSub 是一个可能为空的列表。
  5. 返回 « firstSub » 与 restSub 的列表串接。

13.3.9 可选链

Note
可选链是由一个或多个属性访问和函数调用组成的链,其中第一个以记号 ?. 开始。

13.3.9.1 Runtime Semantics: 求值

OptionalExpression : MemberExpression OptionalChain
  1. baseReference 为 ? 对 MemberExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. 如果 baseValueundefinednull,那么
    1. 返回 undefined
  4. 返回 ? 对 OptionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。
OptionalExpression : CallExpression OptionalChain
  1. baseReference 为 ? 对 CallExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. 如果 baseValueundefinednull,那么
    1. 返回 undefined
  4. 返回 ? 对 OptionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。
OptionalExpression : OptionalExpression OptionalChain
  1. baseReference 为 ? 对 OptionalExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. 如果 baseValueundefinednull,那么
    1. 返回 undefined
  4. 返回 ? 对 OptionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。

13.3.9.2 Runtime Semantics: ChainEvaluation

The syntax-directed operation ChainEvaluation takes arguments baseValue (一个 ECMAScript 语言值) and baseReference (一个 ECMAScript 语言值或一个 Reference Record) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值或一个 Reference Record,要么是一个突然完成. It is defined piecewise over the following productions:

OptionalChain : ?. Arguments
  1. thisChain 为该 OptionalChain
  2. tailCallIsInTailPosition(thisChain)。
  3. 返回 ? EvaluateCall(baseValue, baseReference, Arguments, tailCall)。
OptionalChain : ?. [ Expression ]
  1. strictIsStrict(this OptionalChain)。
  2. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
OptionalChain : ?. IdentifierName
  1. strictIsStrict(this OptionalChain)。
  2. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
OptionalChain : ?. PrivateIdentifier
  1. fieldNameStringPrivateIdentifierStringValue
  2. 返回 MakePrivateReference(baseValue, fieldNameString)。
OptionalChain : OptionalChain Arguments
  1. optionalChainOptionalChain
  2. newReference 为 ? 对 optionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。
  3. newValue 为 ? GetValue(newReference)。
  4. thisChain 为该 OptionalChain
  5. tailCallIsInTailPosition(thisChain)。
  6. 返回 ? EvaluateCall(newValue, newReference, Arguments, tailCall)。
OptionalChain : OptionalChain [ Expression ]
  1. optionalChainOptionalChain
  2. newReference 为 ? 对 optionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。
  3. newValue 为 ? GetValue(newReference)。
  4. strictIsStrict(this OptionalChain)。
  5. 返回 ? EvaluatePropertyAccessWithExpressionKey(newValue, Expression, strict)。
OptionalChain : OptionalChain . IdentifierName
  1. optionalChainOptionalChain
  2. newReference 为 ? 对 optionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。
  3. newValue 为 ? GetValue(newReference)。
  4. strictIsStrict(this OptionalChain)。
  5. 返回 EvaluatePropertyAccessWithIdentifierKey(newValue, IdentifierName, strict)。
OptionalChain : OptionalChain . PrivateIdentifier
  1. optionalChainOptionalChain
  2. newReference 为 ? 对 optionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。
  3. newValue 为 ? GetValue(newReference)。
  4. fieldNameStringPrivateIdentifierStringValue
  5. 返回 MakePrivateReference(newValue, fieldNameString)。

13.3.10 Import 调用

13.3.10.1 Runtime Semantics: 求值

ImportCall : import ( AssignmentExpression ,opt )
  1. 返回 ? EvaluateImportCall(AssignmentExpression)。
ImportCall : import ( AssignmentExpression , AssignmentExpression ,opt )
  1. 返回 ? EvaluateImportCall(第一个 AssignmentExpression, 第二个 AssignmentExpression)。

13.3.10.2 EvaluateImportCall ( specifierExpression [ , optionsExpression ] )

The abstract operation EvaluateImportCall takes argument specifierExpression (一个 Parse Node) and optional argument optionsExpression (一个 Parse Node) and returns 要么是一个正常完成,包含一个 Promise,要么是一个突然完成. It performs the following steps when called:

  1. referrerGetActiveScriptOrModule()。
  2. 如果 referrernull,将 referrer 设为当前 Realm Record
  3. specifierRef 为 ? 对 specifierExpression 求值。
  4. specifier 为 ? GetValue(specifierRef)。
  5. 如果 optionsExpression 存在,那么
    1. optionsRef 为 ? 对 optionsExpression 求值。
    2. options 为 ? GetValue(optionsRef)。
  6. 否则,
    1. optionsundefined
  7. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  8. specifierStringCompletion(ToString(specifier))。
  9. IfAbruptRejectPromise(specifierString, promiseCapability)。
  10. attributes 为一个新的空列表。
  11. 如果 options 不为 undefined,那么
    1. 如果 options 不是一个 Object,那么
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
      2. 返回 promiseCapability.[[Promise]]
    2. attributesObjCompletion(Get(options, "with")).
    3. IfAbruptRejectPromise(attributesObj, promiseCapability)。
    4. 如果 attributesObj 不为 undefined,那么
      1. 如果 attributesObj 不是一个 Object,那么
        1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
        2. 返回 promiseCapability.[[Promise]]
      2. entriesCompletion(EnumerableOwnProperties(attributesObj, key+value))。
      3. IfAbruptRejectPromise(entries, promiseCapability)。
      4. 对于 entries 中的每个元素 entry,执行
        1. key 为 ! Get(entry, "0")。
        2. value 为 ! Get(entry, "1")。
        3. 如果 key 是一个 String,那么
          1. 如果 value 不是一个 String,那么
            1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
            2. 返回 promiseCapability.[[Promise]]
          2. ImportAttribute Record { [[Key]]: key, [[Value]]: value } 追加到 attributes
    5. 如果 AllImportAttributesSupported(attributes) 为 false,那么
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
      2. 返回 promiseCapability.[[Promise]]
    6. 按照 [[Key]] 字段的词法顺序对 attributes 排序,将每个此类字段的值视为 UTF-16 码元值序列。NOTE: 这种排序只在如下意义上可观察:宿主被禁止根据枚举属性的顺序来改变行为。
  12. moduleRequest 为一个新的 ModuleRequest Record { [[Specifier]]: specifierString, [[Attributes]]: attributes }。
  13. 执行 HostLoadImportedModule(referrer, moduleRequest, empty, promiseCapability)。
  14. 返回 promiseCapability.[[Promise]]

13.3.10.3 ContinueDynamicImport ( promiseCapability, moduleCompletion )

The abstract operation ContinueDynamicImport takes arguments promiseCapability (一个 PromiseCapability Record) and moduleCompletion (要么是一个正常完成,包含一个 Module Record,要么是一个抛出完成) and returns unused. 它完成最初由一次 import() 调用发起的动态导入过程,并视情况解析或拒绝该调用返回的 promise。 It performs the following steps when called:

  1. 如果 moduleCompletion 是一个突然完成,那么
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « moduleCompletion.[[Value]] »)。
    2. 返回 unused
  2. modulemoduleCompletion.[[Value]]
  3. loadPromisemodule.LoadRequestedModules()。
  4. rejectedClosure 为一个新的抽象闭包,带参数 (reason),它捕获 promiseCapability 并在被调用时执行以下步骤:
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « reason »)。
    2. 返回 NormalCompletion(undefined)。
  5. onRejectedCreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  6. linkAndEvaluateClosure 为一个新的不带参数的抽象闭包,它捕获 modulepromiseCapabilityonRejected,并在被调用时执行以下步骤:
    1. linkCompletion(module.Link())。
    2. 如果 link 是一个突然完成,那么
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « link.[[Value]] »)。
      2. 返回 NormalCompletion(undefined)。
    3. evaluatePromisemodule.Evaluate()。
    4. fulfilledClosure 为一个新的不带参数的抽象闭包,它捕获 modulepromiseCapability,并在被调用时执行以下步骤:
      1. namespaceGetModuleNamespace(module)。
      2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « namespace »)。
      3. 返回 NormalCompletion(undefined)。
    5. onFulfilledCreateBuiltinFunction(fulfilledClosure, 0, "", « »)。
    6. 执行 PerformPromiseThen(evaluatePromise, onFulfilled, onRejected)。
    7. 返回 unused
  7. linkAndEvaluateCreateBuiltinFunction(linkAndEvaluateClosure, 0, "", « »)。
  8. 执行 PerformPromiseThen(loadPromise, linkAndEvaluate, onRejected)。
  9. 返回 unused

13.3.11 带标签模板

Note

带标签模板是一种函数调用,其中调用的参数来自一个 TemplateLiteral13.2.8)。实际参数包括一 个模板对象(13.2.8.4)以及 对嵌入在 TemplateLiteral 中的表达式求值所产生的值。

13.3.11.1 Runtime Semantics: 求值

MemberExpression : MemberExpression TemplateLiteral
  1. tagRef 为 ? 对 MemberExpression 求值。
  2. tagFunc 为 ? GetValue(tagRef)。
  3. thisCall 为该 MemberExpression
  4. tailCallIsInTailPosition(thisCall)。
  5. 返回 ? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall)。
CallExpression : CallExpression TemplateLiteral
  1. tagRef 为 ? 对 CallExpression 求值。
  2. tagFunc 为 ? GetValue(tagRef)。
  3. thisCall 为该 CallExpression
  4. tailCallIsInTailPosition(thisCall)。
  5. 返回 ? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall)。

13.3.12 元属性

13.3.12.1 Runtime Semantics: 求值

NewTarget : new . target
  1. 返回 GetNewTarget()。
ImportMeta : import . meta
  1. moduleGetActiveScriptOrModule()。
  2. 断言:module 是一个 Source Text Module Record
  3. importMetamodule.[[ImportMeta]]
  4. 如果 importMetaempty,那么
    1. importMeta 设为 OrdinaryObjectCreate(null)。
    2. importMetaValuesHostGetImportMetaProperties(module)。
    3. 对于 importMetaValues 中的每个 Record { [[Key]], [[Value]] } p,执行
      1. 执行 ! CreateDataPropertyOrThrow(importMeta, p.[[Key]], p.[[Value]])。
    4. 执行 HostFinalizeImportMeta(importMeta, module)。
    5. module.[[ImportMeta]] 设为 importMeta
    6. 返回 importMeta
  5. 断言:importMeta 是一个 Object。
  6. 返回 importMeta

13.3.12.1.1 HostGetImportMetaProperties ( moduleRecord )

The host-defined abstract operation HostGetImportMetaProperties takes argument moduleRecord (一个 Module Record) and returns 一个列表,其元素为具有字段 [[Key]](一个属性键)和 [[Value]](一个 ECMAScript 语言值)的 Record. 它允许宿主import.meta 返回的对象提供属性键和值。

HostGetImportMetaProperties 的默认实现是返回一个新的空列表。

13.3.12.1.2 HostFinalizeImportMeta ( importMeta, moduleRecord )

The host-defined abstract operation HostFinalizeImportMeta takes arguments importMeta (一个 Object) and moduleRecord (一个 Module Record) and returns unused. 它允许宿主执行任意非常规操作,以准备 import.meta 返回的对象。

大多数宿主只需定义 HostGetImportMetaProperties,并保留 HostFinalizeImportMeta 的默认行为即可。不过,HostFinalizeImportMeta 为那些在将对象暴露给 ECMAScript 代码之前需要直接操纵它的宿主提供了一个 “逃生口”。

HostFinalizeImportMeta 的默认实现是返回 unused

13.4 更新表达式

语法

UpdateExpression[Yield, Await] : LeftHandSideExpression[?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] ++ LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] -- ++ UnaryExpression[?Yield, ?Await] -- UnaryExpression[?Yield, ?Await]

13.4.1 Static Semantics: 早期错误

UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- UpdateExpression : ++ UnaryExpression -- UnaryExpression

13.4.2 后缀递增运算符

13.4.2.1 Runtime Semantics: 求值

UpdateExpression : LeftHandSideExpression ++
  1. lhs 为 ? 对 LeftHandSideExpression 求值。
  2. 如果 LeftHandSideExpressionAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
  3. oldValue 为 ? ToNumeric(? GetValue(lhs))。
  4. 如果 oldValue 是一个 Number,那么
    1. newValueNumber::add(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是一个 BigInt。
    2. newValueBigInt::add(oldValue, 1)。
  6. 执行 ? PutValue(lhs, newValue)。
  7. 返回 oldValue

13.4.3 后缀递减运算符

13.4.3.1 Runtime Semantics: 求值

UpdateExpression : LeftHandSideExpression --
  1. lhs 为 ? 对 LeftHandSideExpression 求值。
  2. 如果 LeftHandSideExpressionAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
  3. oldValue 为 ? ToNumeric(? GetValue(lhs))。
  4. 如果 oldValue 是一个 Number,那么
    1. newValueNumber::subtract(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是一个 BigInt。
    2. newValueBigInt::subtract(oldValue, 1)。
  6. 执行 ? PutValue(lhs, newValue)。
  7. 返回 oldValue

13.4.4 前缀递增运算符

13.4.4.1 Runtime Semantics: 求值

UpdateExpression : ++ UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. 如果 UnaryExpressionAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
  3. oldValue 为 ? ToNumeric(? GetValue(expr))。
  4. 如果 oldValue 是一个 Number,那么
    1. newValueNumber::add(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是一个 BigInt。
    2. newValueBigInt::add(oldValue, 1)。
  6. 执行 ? PutValue(expr, newValue)。
  7. 返回 newValue

13.4.5 前缀递减运算符

13.4.5.1 Runtime Semantics: 求值

UpdateExpression : -- UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. 如果 UnaryExpressionAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
  3. oldValue 为 ? ToNumeric(? GetValue(expr))。
  4. 如果 oldValue 是一个 Number,那么
    1. newValueNumber::subtract(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是一个 BigInt。
    2. newValueBigInt::subtract(oldValue, 1)。
  6. 执行 ? PutValue(expr, newValue)。
  7. 返回 newValue

13.5 一元运算符

语法

UnaryExpression[Yield, Await] : UpdateExpression[?Yield, ?Await] delete UnaryExpression[?Yield, ?Await] void UnaryExpression[?Yield, ?Await] typeof UnaryExpression[?Yield, ?Await] + UnaryExpression[?Yield, ?Await] - UnaryExpression[?Yield, ?Await] ~ UnaryExpression[?Yield, ?Await] ! UnaryExpression[?Yield, ?Await] [+Await] AwaitExpression[?Yield]

13.5.1 delete 运算符

13.5.1.1 Static Semantics: 早期错误

UnaryExpression : delete UnaryExpression Note

最后一条规则意味着,像 delete (((foo))) 这样的表达式会由于递归应 用第一条规则而产生早期错误

13.5.1.2 Runtime Semantics: 求值

UnaryExpression : delete UnaryExpression
  1. ref 为 ? 对 UnaryExpression 求值。
  2. 如果 ref 不是一个 Reference Record,返回 true
  3. 如果 IsUnresolvableReference(ref) 为 true,那么
    1. 断言:ref.[[Strict]]false
    2. 返回 true
  4. 如果 IsPropertyReference(ref) 为 true,那么
    1. 断言:IsPrivateReference(ref) 为 false
    2. 如果 IsSuperReference(ref) 为 true,抛出一个 ReferenceError 异常。
    3. baseObj 为 ? ToObject(ref.[[Base]])。
    4. 如果 ref.[[ReferencedName]] 不是一个属性键,那么
      1. ref.[[ReferencedName]] 设为 ? ToPropertyKey(ref.[[ReferencedName]])。
    5. deleteStatus 为 ? baseObj.[[Delete]](ref.[[ReferencedName]])
    6. 如果 deleteStatusfalseref.[[Strict]]true,抛出一个 TypeError 异常。
    7. 返回 deleteStatus
  5. baseref.[[Base]]
  6. 断言:base 是一个 Environment Record
  7. 返回 ? base.DeleteBinding(ref.[[ReferencedName]])
Note 1

当一个 delete 运算符出现在严格模式代码中时,如果它的 UnaryExpression 是对变量、函数参数或函数名的直接引用,则会抛出一个 SyntaxError 异常。此外,如果 delete 运算符出现在严格模式代码中, 并且要删除的属性具有特性 { [[Configurable]]: false }(或者因其他原 因不可删除),则会抛出一个 TypeError 异常。

Note 2

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

13.5.2 void 运算符

13.5.2.1 Runtime Semantics: 求值

UnaryExpression : void UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. 执行 ? GetValue(expr)。
  3. 返回 undefined
Note

即使不会使用其值,也必须调用 GetValue,因为它可能具有可观察的副作用。

13.5.3 typeof 运算符

13.5.3.1 Runtime Semantics: 求值

UnaryExpression : typeof UnaryExpression
  1. val 为 ? 对 UnaryExpression 求值。
  2. 如果 val 是一个 Reference Record,那么
    1. 如果 IsUnresolvableReference(val) 为 true,返回 "undefined"
  3. val 设为 ? GetValue(val)。
  4. 如果 valundefined,返回 "undefined"
  5. 如果 valnull,返回 "object"
  6. 如果 val 是一个 String,返回 "string"
  7. 如果 val 是一个 Symbol,返回 "symbol"
  8. 如果 val 是一个 Boolean,返回 "boolean"
  9. 如果 val 是一个 Number,返回 "number"
  10. 如果 val 是一个 BigInt,返回 "bigint"
  11. 断言:val 是一个 Object。
  12. Normative Optional
    如果宿主是 Web 浏览器,或以其他方式支持 [[IsHTMLDDA]] 内部槽,那么
    1. 如果 val 具有 [[IsHTMLDDA]] 内部槽,返回 "undefined"
  13. 如果 val 具有 [[Call]] 内部方法,返回 "function"
  14. 返回 "object"

13.5.4 一元 + 运算符

Note

一元 + 运算符会将其操作数转换为 Number 类型

13.5.4.1 Runtime Semantics: 求值

UnaryExpression : + UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. 返回 ? ToNumber(? GetValue(expr))。

13.5.5 一元 - 运算符

Note

一元 - 运算符会将其操作数转换为一个数值,然后对其取反。对 +0𝔽 取反会得到 -0𝔽,而对 -0𝔽 取反会得到 +0𝔽

13.5.5.1 Runtime Semantics: 求值

UnaryExpression : - UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是一个 Number,返回 Number::unaryMinus(oldValue)。
  4. 断言:oldValue 是一个 BigInt。
  5. 返回 BigInt::unaryMinus(oldValue)。

13.5.6 按位非运算符 ( ~ )

13.5.6.1 Runtime Semantics: 求值

UnaryExpression : ~ UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是一个 Number,返回 Number::bitwiseNOT(oldValue)。
  4. 断言:oldValue 是一个 BigInt。
  5. 返回 BigInt::bitwiseNOT(oldValue)。

13.5.7 逻辑非运算符 ( ! )

13.5.7.1 Runtime Semantics: 求值

UnaryExpression : ! UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. oldValueToBoolean(? GetValue(expr))。
  3. 如果 oldValuetrue,返回 false
  4. 返回 true

13.6 指数运算符

语法

ExponentiationExpression[Yield, Await] : UnaryExpression[?Yield, ?Await] UpdateExpression[?Yield, ?Await] ** ExponentiationExpression[?Yield, ?Await]

13.6.1 Runtime Semantics: 求值

ExponentiationExpression : UpdateExpression ** ExponentiationExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(UpdateExpression, **, ExponentiationExpression)。

13.7 乘法运算符

语法

MultiplicativeExpression[Yield, Await] : ExponentiationExpression[?Yield, ?Await] MultiplicativeExpression[?Yield, ?Await] MultiplicativeOperator ExponentiationExpression[?Yield, ?Await] MultiplicativeOperator : one of * / % Note
  • * 运算符执行乘法,产生其操作数的乘积。
  • / 运算符执行除法,产生其操作数的商。
  • % 运算符产生其操作数在一个隐含除法中的余数。

13.7.1 Runtime Semantics: 求值

MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression
  1. opTextMultiplicativeOperator匹配的源文本
  2. 返回 ? EvaluateStringOrNumericBinaryExpression(MultiplicativeExpression, opText, ExponentiationExpression)。

13.8 加法运算符

语法

AdditiveExpression[Yield, Await] : MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] + MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] - MultiplicativeExpression[?Yield, ?Await]

13.8.1 加法运算符 ( + )

Note

加法运算符要么执行字符串串接,要么执行数值加法。

13.8.1.1 Runtime Semantics: 求值

AdditiveExpression : AdditiveExpression + MultiplicativeExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(AdditiveExpression, +, MultiplicativeExpression)。

13.8.2 减法运算符 ( - )

Note

- 运算符执行减法,产生其操作数的差。

13.8.2.1 Runtime Semantics: 求值

AdditiveExpression : AdditiveExpression - MultiplicativeExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(AdditiveExpression, -, MultiplicativeExpression)。

13.9 按位移位运算符

语法

ShiftExpression[Yield, Await] : AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] << AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >> AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >>> AdditiveExpression[?Yield, ?Await]

13.9.1 左移运算符 ( << )

Note

对左操作数执行按位左移,移位的位数由右操作数指定。

13.9.1.1 Runtime Semantics: 求值

ShiftExpression : ShiftExpression << AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, <<, AdditiveExpression)。

13.9.2 有符号右移运算符 ( >> )

Note

对左操作数执行符号扩展的按位右移,移位的位数由右操作数指定。

13.9.2.1 Runtime Semantics: 求值

ShiftExpression : ShiftExpression >> AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>, AdditiveExpression)。

13.9.3 无符号右移运算符 ( >>> )

Note

对左操作数执行零扩展的按位右移,移位的位数由右操作数指定。

13.9.3.1 Runtime Semantics: 求值

ShiftExpression : ShiftExpression >>> AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>>, AdditiveExpression)。

13.10 关系运算符

Note 1

对关系运算符求值的结果总是 Boolean 类型,反映该运算符所命名的关系是否在 其两个操作数之间成立。

语法

RelationalExpression[In, Yield, Await] : ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] < ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] > ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] <= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] >= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] instanceof ShiftExpression[?Yield, ?Await] [+In] RelationalExpression[+In, ?Yield, ?Await] in ShiftExpression[?Yield, ?Await] [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await] Note 2

[In] 文法参数是必需的,以避免将关系表达式中的 in 运算符与 for 语句中的 in 运算符混淆。

13.10.1 Runtime Semantics: 求值

RelationalExpression : RelationalExpression < ShiftExpression
  1. lRef 为 ? 对 RelationalExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 ShiftExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. result 为 ? IsLessThan(lVal, rVal, true)。
  6. 如果 resultundefined,返回 false
  7. 返回 result
RelationalExpression : RelationalExpression > ShiftExpression
  1. lRef 为 ? 对 RelationalExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 ShiftExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. result 为 ? IsLessThan(rVal, lVal, false)。
  6. 如果 resultundefined,返回 false
  7. 返回 result
RelationalExpression : RelationalExpression <= ShiftExpression
  1. lRef 为 ? 对 RelationalExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 ShiftExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. result 为 ? IsLessThan(rVal, lVal, false)。
  6. 如果 resulttrueundefined,返回 false
  7. 返回 true
RelationalExpression : RelationalExpression >= ShiftExpression
  1. lRef 为 ? 对 RelationalExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 ShiftExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. result 为 ? IsLessThan(lVal, rVal, true)。
  6. 如果 resulttrueundefined,返回 false
  7. 返回 true
RelationalExpression : RelationalExpression instanceof ShiftExpression
  1. lRef 为 ? 对 RelationalExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 ShiftExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 ? InstanceofOperator(lVal, rVal)。
RelationalExpression : RelationalExpression in ShiftExpression
  1. lRef 为 ? 对 RelationalExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 ShiftExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. 如果 rVal 不是一个 Object,抛出一个 TypeError 异常。
  6. 返回 ? HasProperty(rVal, ? ToPropertyKey(lVal))。
RelationalExpression : PrivateIdentifier in ShiftExpression
  1. privateIdentifierPrivateIdentifierStringValue
  2. rRef 为 ? 对 ShiftExpression 求值。
  3. rVal 为 ? GetValue(rRef)。
  4. 如果 rVal 不是一个 Object,抛出一个 TypeError 异常。
  5. privateEnv 为当前运行执行上下文的 PrivateEnvironment。
  6. 断言:privateEnv 不为 null
  7. privateNameResolvePrivateIdentifier(privateEnv, privateIdentifier)。
  8. 如果 PrivateElementFind(rVal, privateName) 为 empty,返回 false
  9. 返回 true

13.10.2 InstanceofOperator ( value, target )

The abstract operation InstanceofOperator takes arguments value (一个 ECMAScript 语言值) and target (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. 它实现了用于判定 value 是否是 target 的实例的通用算法:要么查阅 target%Symbol.hasInstance% 方法,要么(如果该方法不存在)通过判定 target"prototype" 属性值是否出现在 value 的原型链中来完成。 It performs the following steps when called:

  1. 如果 target 不是一个 Object,抛出一个 TypeError 异常。
  2. instOfHandler 为 ? GetMethod(target, %Symbol.hasInstance%)。
  3. 如果 instOfHandler 不为 undefined,那么
    1. 返回 ToBoolean(? Call(instOfHandler, target, « value »))。
  4. 如果 IsCallable(target) 为 false,抛出一个 TypeError 异常。
  5. 返回 ? OrdinaryHasInstance(target, value)。
Note

步骤 45 提供了与 ECMAScript 先前版本的兼容性;那些版本并未使用 %Symbol.hasInstance% 方法来定义 instanceof 运算符的语义。如果一个对象没有定义或继承 %Symbol.hasInstance%,则会使用默认的 instanceof 语义。

13.11 相等运算符

Note

对相等运算符求值的结果总是 Boolean 类型,反映该运算符所命名的关系是否在 其两个操作数之间成立。

语法

EqualityExpression[In, Yield, Await] : RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] == RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] != RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] === RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] !== RelationalExpression[?In, ?Yield, ?Await]

13.11.1 Runtime Semantics: 求值

EqualityExpression : EqualityExpression == RelationalExpression
  1. lRef 为 ? 对 EqualityExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 RelationalExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 ? IsLooselyEqual(rVal, lVal)。
EqualityExpression : EqualityExpression != RelationalExpression
  1. lRef 为 ? 对 EqualityExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 RelationalExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. r 为 ? IsLooselyEqual(rVal, lVal)。
  6. 如果 rtrue,返回 false
  7. 返回 true
EqualityExpression : EqualityExpression === RelationalExpression
  1. lRef 为 ? 对 EqualityExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 RelationalExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 IsStrictlyEqual(rVal, lVal)。
EqualityExpression : EqualityExpression !== RelationalExpression
  1. lRef 为 ? 对 EqualityExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 RelationalExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. rIsStrictlyEqual(rVal, lVal)。
  6. 如果 rtrue,返回 false
  7. 返回 true
Note 1

相等运算符保持以下不变量:

  • A != B 等价于 !(A == B)
  • A == B 等价于 B == A,除了 AB 的求值顺序不同之外。
Note 2

相等运算符并不总是具有传递性。例如,可能存在两个不同的 String 对象, 它们都表示相同的 String 值;每个 String 对象都会被 == 运算符视为与该 String 值相等,但这两个 String 对象彼此并不相等。例如:

  • new String("a") == "a""a" == new String("a") 都为 true
  • new String("a") == new String("a")false
Note 3

String 的比较使用的是对码元值序列的简单相等测试。不会尝试使用 Unicode 规范中定义的、更复杂且更偏语义化的字符或字符串相等与排序定义。因此,根据 Unicode 标准属于规范相等的 String 值,测试结果可能并不相等。实际上,该算 法假定两个 String 都已经处于规范化形式。

13.12 二元按位运算符

语法

BitwiseANDExpression[In, Yield, Await] : EqualityExpression[?In, ?Yield, ?Await] BitwiseANDExpression[?In, ?Yield, ?Await] & EqualityExpression[?In, ?Yield, ?Await] BitwiseXORExpression[In, Yield, Await] : BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseXORExpression[?In, ?Yield, ?Await] ^ BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseORExpression[In, Yield, Await] : BitwiseXORExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] | BitwiseXORExpression[?In, ?Yield, ?Await]

13.12.1 Runtime Semantics: 求值

BitwiseANDExpression : BitwiseANDExpression & EqualityExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(BitwiseANDExpression, &, EqualityExpression)。
BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(BitwiseXORExpression, ^, BitwiseANDExpression)。
BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(BitwiseORExpression, |, BitwiseXORExpression)。

13.13 二元逻辑运算符

语法

LogicalANDExpression[In, Yield, Await] : BitwiseORExpression[?In, ?Yield, ?Await] LogicalANDExpression[?In, ?Yield, ?Await] && BitwiseORExpression[?In, ?Yield, ?Await] LogicalORExpression[In, Yield, Await] : LogicalANDExpression[?In, ?Yield, ?Await] LogicalORExpression[?In, ?Yield, ?Await] || LogicalANDExpression[?In, ?Yield, ?Await] CoalesceExpression[In, Yield, Await] : CoalesceExpressionHead[?In, ?Yield, ?Await] ?? BitwiseORExpression[?In, ?Yield, ?Await] CoalesceExpressionHead[In, Yield, Await] : CoalesceExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] ShortCircuitExpression[In, Yield, Await] : LogicalORExpression[?In, ?Yield, ?Await] CoalesceExpression[?In, ?Yield, ?Await] Note

&&|| 运算符所产生的值不一定是 Boolean 类型。产生的值总是两个操作数表达式之一的值。

13.13.1 Runtime Semantics: 求值

LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
  1. lRef 为 ? 对 LogicalANDExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 为 false,返回 lVal
  4. rRef 为 ? 对 BitwiseORExpression 求值。
  5. 返回 ? GetValue(rRef)。
LogicalORExpression : LogicalORExpression || LogicalANDExpression
  1. lRef 为 ? 对 LogicalORExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 为 true,返回 lVal
  4. rRef 为 ? 对 LogicalANDExpression 求值。
  5. 返回 ? GetValue(rRef)。
CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression
  1. lRef 为 ? 对 CoalesceExpressionHead 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 lVal 既不是 undefined 也不是 null,返回 lVal
  4. rRef 为 ? 对 BitwiseORExpression 求值。
  5. 返回 ? GetValue(rRef)。

13.14 条件运算符 ( ? : )

语法

ConditionalExpression[In, Yield, Await] : ShortCircuitExpression[?In, ?Yield, ?Await] ShortCircuitExpression[?In, ?Yield, ?Await] ? AssignmentExpression[+In, ?Yield, ?Await] : AssignmentExpression[?In, ?Yield, ?Await] Note

ECMAScript 中 ConditionalExpression 的文法与 C 和 Java 稍有不同;后 两者都允许第二个子表达式是一个 Expression,但将第三个表达式限制为一个 ConditionalExpression。ECMAScript 采用这种差异化设计的动机,是为了允 许赋值表达式受条件两支中的任一支控制,并消除将逗号表达式作为中间表达式这一 令人困惑且几乎无用的情形。

13.14.1 Runtime Semantics: 求值

ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression
  1. lRef 为 ? 对 ShortCircuitExpression 求值。
  2. lValToBoolean(? GetValue(lRef))。
  3. 如果 lValtrue,那么
    1. trueRef 为 ? 对第一个 AssignmentExpression 求值。
    2. 返回 ? GetValue(trueRef)。
  4. falseRef 为 ? 对第二个 AssignmentExpression 求值。
  5. 返回 ? GetValue(falseRef)。

13.15 赋值运算符

语法

AssignmentExpression[In, Yield, Await] : ConditionalExpression[?In, ?Yield, ?Await] [+Yield] YieldExpression[?In, ?Await] ArrowFunction[?In, ?Yield, ?Await] AsyncArrowFunction[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] = AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] AssignmentOperator AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] &&= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ||= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ??= AssignmentExpression[?In, ?Yield, ?Await] AssignmentOperator : one of *= /= %= += -= <<= >>= >>>= &= ^= |= **=

13.15.1 Static Semantics: 早期错误

AssignmentExpression : LeftHandSideExpression = AssignmentExpression AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression

13.15.2 Runtime Semantics: 求值

AssignmentExpression : LeftHandSideExpression = AssignmentExpression
  1. 如果 LeftHandSideExpression 既不是 ObjectLiteral 也不是 ArrayLiteral,那么
    1. lRef 为 ? 对 LeftHandSideExpression 求值。
    2. 如果 LeftHandSideExpressionAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
    3. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 trueIsIdentifierRef of LeftHandSideExpressiontrue,那么
      1. lhsLeftHandSideExpressionStringValue
      2. rVal 为 ? 对 AssignmentExpression 执行 NamedEvaluation,并以 lhs 为参数。
    4. 否则,
      1. rRef 为 ? 对 AssignmentExpression 求值。
      2. rVal 为 ? GetValue(rRef)。
    5. 执行 ? PutValue(lRef, rVal)。
    6. 返回 rVal
  2. assignmentPattern 为被 LeftHandSideExpression 覆盖AssignmentPattern
  3. rRef 为 ? 对 AssignmentExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. 执行 ? 对 assignmentPattern 执行 DestructuringAssignmentEvaluation,并以 rVal 为参数。
  6. 返回 rVal
AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression
  1. lRef 为 ? 对 LeftHandSideExpression 求值。
  2. 如果 LeftHandSideExpressionAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
  3. lVal 为 ? GetValue(lRef)。
  4. rRef 为 ? 对 AssignmentExpression 求值。
  5. rVal 为 ? GetValue(rRef)。
  6. assignmentOpTextAssignmentOperator匹配的源文本
  7. opText 为与 assignmentOpText 在下表中对应的 Unicode 码点序列:
    assignmentOpText opText
    **= **
    *= *
    /= /
    %= %
    += +
    -= -
    <<= <<
    >>= >>
    >>>= >>>
    &= &
    ^= ^
    |= |
  8. r 为 ? ApplyStringOrNumericBinaryOperator(lVal, opText, rVal)。
  9. 执行 ? PutValue(lRef, r)。
  10. 返回 r
AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression
  1. lRef 为 ? 对 LeftHandSideExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 为 false,返回 lVal
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 trueIsIdentifierRef of LeftHandSideExpressiontrue,那么
    1. lhsLeftHandSideExpressionStringValue
    2. rVal 为 ? 对 AssignmentExpression 执行 NamedEvaluation,并以 lhs 为参数。
  5. 否则,
    1. rRef 为 ? 对 AssignmentExpression 求值。
    2. rVal 为 ? GetValue(rRef)。
  6. 执行 ? PutValue(lRef, rVal)。
  7. 返回 rVal
AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression
  1. lRef 为 ? 对 LeftHandSideExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 为 true,返回 lVal
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 trueIsIdentifierRef of LeftHandSideExpressiontrue,那么
    1. lhsLeftHandSideExpressionStringValue
    2. rVal 为 ? 对 AssignmentExpression 执行 NamedEvaluation,并以 lhs 为参数。
  5. 否则,
    1. rRef 为 ? 对 AssignmentExpression 求值。
    2. rVal 为 ? GetValue(rRef)。
  6. 执行 ? PutValue(lRef, rVal)。
  7. 返回 rVal
AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression
  1. lRef 为 ? 对 LeftHandSideExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 lVal 既不是 undefined 也不是 null,返回 lVal
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 trueIsIdentifierRef of LeftHandSideExpressiontrue,那么
    1. lhsLeftHandSideExpressionStringValue
    2. rVal 为 ? 对 AssignmentExpression 执行 NamedEvaluation,并以 lhs 为参数。
  5. 否则,
    1. rRef 为 ? 对 AssignmentExpression 求值。
    2. rVal 为 ? GetValue(rRef)。
  6. 执行 ? PutValue(lRef, rVal)。
  7. 返回 rVal
Note

当该表达式出现在严格模式代码中时,如果步骤 1.e3222 中的 lRef 是一个不可解析引用,则会发生运行时错误。如果是这种情况,会抛出 一个 ReferenceError 异常。此外,如果步骤 9666 中的 lRef 是对某个数据属性的引用,而该属性具有特性值 { [[Writable]]: false },或者是对某个访问器属性的引用,而该属性具有特 性值 { [[Set]]: undefined },或者是对某个不可扩展对象上不存在属性的引 用,则也会发生运行时错误。在这些情况下会抛出一个 TypeError 异常。

13.15.3 ApplyStringOrNumericBinaryOperator ( lVal, opText, rVal )

The abstract operation ApplyStringOrNumericBinaryOperator takes arguments lVal (一个 ECMAScript 语言值), opText (***/%+-<<>>>>>&^|), and rVal (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 String、一个 BigInt 或一个 Number,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 opText+,那么
    1. lPrim 为 ? ToPrimitive(lVal)。
    2. rPrim 为 ? ToPrimitive(rVal)。
    3. 如果 lPrim 是一个 String 或 rPrim 是一个 String,那么
      1. lStr 为 ? ToString(lPrim)。
      2. rStr 为 ? ToString(rPrim)。
      3. 返回 lStrrStr 的字符串串接结果。
    4. lVal 设为 lPrim
    5. rVal 设为 rPrim
  2. NOTE: 到此为止,它必须是一个数值运算。
  3. lNum 为 ? ToNumeric(lVal)。
  4. rNum 为 ? ToNumeric(rVal)。
  5. 如果 SameType(lNum, rNum) 为 false,抛出一个 TypeError 异常。
  6. 如果 lNum 是一个 BigInt,那么
    1. 如果 opText**,返回 ? BigInt::exponentiate(lNum, rNum)。
    2. 如果 opText/,返回 ? BigInt::divide(lNum, rNum)。
    3. 如果 opText%,返回 ? BigInt::remainder(lNum, rNum)。
    4. 如果 opText>>>,返回 ? BigInt::unsignedRightShift(lNum, rNum)。
    5. operation 为下表中与 opText 关联的抽象操作
      opText operation
      * BigInt::multiply
      + BigInt::add
      - BigInt::subtract
      << BigInt::leftShift
      >> BigInt::signedRightShift
      & BigInt::bitwiseAND
      ^ BigInt::bitwiseXOR
      | BigInt::bitwiseOR
  7. 否则,
    1. 断言:lNum 是一个 Number。
    2. operation 为下表中与 opText 关联的抽象操作
      opText operation
      ** Number::exponentiate
      * Number::multiply
      / Number::divide
      % Number::remainder
      + Number::add
      - Number::subtract
      << Number::leftShift
      >> Number::signedRightShift
      >>> Number::unsignedRightShift
      & Number::bitwiseAND
      ^ Number::bitwiseXOR
      | Number::bitwiseOR
  8. 返回 operation(lNum, rNum)。
Note 1

在步骤 1.a1.b 中对 ToPrimitive 的调用没有提供 hint。除 Date 外,所有标准对象在缺少 hint 时都按给出 number 的方式处理;Date 在缺少 hint 时则按给出 string 的方式处理。异质对象可能会以其他方式处理缺少 hint 的情况。

Note 2

步骤 1.cIsLessThan 算法的步骤 3 不同, 这里使用逻辑或运算,而不是逻辑与运算。

13.15.4 EvaluateStringOrNumericBinaryExpression ( leftOperand, opText, rightOperand )

The abstract operation EvaluateStringOrNumericBinaryExpression takes arguments leftOperand (a Parse Node), opText (**, *, /, %, +, -, <<, >>, >>>, &, ^, or |), and rightOperand (a Parse Node) and returns either a normal completion containing either a String, a BigInt, or a Number, or an abrupt completion. It performs the following steps when called:

  1. lRef 为 ? 对 leftOperand 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 rightOperand 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 ? ApplyStringOrNumericBinaryOperator(lVal, opText, rVal)。

13.15.5 解构赋值

补充语法

在某些情况下,当处理如下产生式的一个实例时
AssignmentExpression : LeftHandSideExpression = AssignmentExpression
LeftHandSideExpression 的解释会使用如下文法加以细化:

AssignmentPattern[Yield, Await] : ObjectAssignmentPattern[?Yield, ?Await] ArrayAssignmentPattern[?Yield, ?Await] ObjectAssignmentPattern[Yield, Await] : { } { AssignmentRestProperty[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] , AssignmentRestProperty[?Yield, ?Await]opt } ArrayAssignmentPattern[Yield, Await] : [ Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] [ AssignmentElementList[?Yield, ?Await] ] [ AssignmentElementList[?Yield, ?Await] , Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] AssignmentRestProperty[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] AssignmentPropertyList[Yield, Await] : AssignmentProperty[?Yield, ?Await] AssignmentPropertyList[?Yield, ?Await] , AssignmentProperty[?Yield, ?Await] AssignmentElementList[Yield, Await] : AssignmentElisionElement[?Yield, ?Await] AssignmentElementList[?Yield, ?Await] , AssignmentElisionElement[?Yield, ?Await] AssignmentElisionElement[Yield, Await] : Elisionopt AssignmentElement[?Yield, ?Await] AssignmentProperty[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt PropertyName[?Yield, ?Await] : AssignmentElement[?Yield, ?Await] AssignmentElement[Yield, Await] : DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt AssignmentRestElement[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] DestructuringAssignmentTarget[Yield, Await] : LeftHandSideExpression[?Yield, ?Await]

13.15.5.1 Static Semantics: 早期错误

AssignmentProperty : IdentifierReference Initializeropt AssignmentRestProperty : ... DestructuringAssignmentTarget DestructuringAssignmentTarget : LeftHandSideExpression

13.15.5.2 Runtime Semantics: DestructuringAssignmentEvaluation

The syntax-directed operation DestructuringAssignmentEvaluation takes argument value (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成. It is defined piecewise over the following productions:

ObjectAssignmentPattern : { }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 返回 unused
ObjectAssignmentPattern : { AssignmentPropertyList } { AssignmentPropertyList , }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 执行 ? 对 AssignmentPropertyList 执行 PropertyDestructuringAssignmentEvaluation,并以 value 为参数。
  3. 返回 unused
ObjectAssignmentPattern : { AssignmentRestProperty }
  1. 执行 ? RequireObjectCoercible(value)。
  2. excludedNames 为一个新的空列表。
  3. 返回 ? 对 AssignmentRestProperty 执行 RestDestructuringAssignmentEvaluation,并以 valueexcludedNames 为参数。
ObjectAssignmentPattern : { AssignmentPropertyList , AssignmentRestProperty }
  1. 执行 ? RequireObjectCoercible(value)。
  2. excludedNames 为 ? 对 AssignmentPropertyList 执行 PropertyDestructuringAssignmentEvaluation,并以 value 为参数。
  3. 返回 ? 对 AssignmentRestProperty 执行 RestDestructuringAssignmentEvaluation,并以 valueexcludedNames 为参数。
ArrayAssignmentPattern : [ ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. 返回 ? IteratorClose(iteratorRecord, NormalCompletion(unused))。
ArrayAssignmentPattern : [ Elision ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. resultCompletion(对 Elision 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
  3. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 result
ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. 如果 Elision 存在,那么
    1. statusCompletion(对 Elision 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
    2. 如果 status 是一个突然完成,那么
      1. 断言:iteratorRecord.[[Done]]true
      2. 返回 ? status
  3. resultCompletion(对 AssignmentRestElement 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
  4. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, result)。
  5. 返回 result
ArrayAssignmentPattern : [ AssignmentElementList ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. resultCompletion(对 AssignmentElementList 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
  3. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 result
ArrayAssignmentPattern : [ AssignmentElementList , Elisionopt AssignmentRestElementopt ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. statusCompletion(对 AssignmentElementList 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
  3. 如果 status 是一个突然完成,那么
    1. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, status)。
    2. 返回 ? status
  4. 如果 Elision 存在,那么
    1. status 设为 Completion(对 Elision 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
    2. 如果 status 是一个突然完成,那么
      1. 断言:iteratorRecord.[[Done]]true
      2. 返回 ? status
  5. 如果 AssignmentRestElement 存在,那么
    1. status 设为 Completion(对 AssignmentRestElement 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
  6. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, status)。
  7. 返回 ? status

13.15.5.3 Runtime Semantics: PropertyDestructuringAssignmentEvaluation

The syntax-directed operation PropertyDestructuringAssignmentEvaluation takes argument value (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个属性键列表,要么是一个突然完成. 它收集所有被解构属性键的列表。 It is defined piecewise over the following productions:

AssignmentPropertyList : AssignmentPropertyList , AssignmentProperty
  1. propertyNames 为 ? 对 AssignmentPropertyList 执行 PropertyDestructuringAssignmentEvaluation,并以 value 为参数。
  2. nextNames 为 ? 对 AssignmentProperty 执行 PropertyDestructuringAssignmentEvaluation,并以 value 为参数。
  3. 返回 propertyNamesnextNames 的列表串接。
AssignmentProperty : IdentifierReference Initializeropt
  1. propertyNameIdentifierReferenceStringValue
  2. lRef 为 ? ResolveBinding(propertyName)。
  3. v 为 ? GetV(value, propertyName)。
  4. 如果 Initializer 存在且 vundefined,那么
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 为 true,那么
      1. v 设为 ? 对 Initializer 执行 NamedEvaluation,并以 propertyName 为参数。
    2. 否则,
      1. defaultValue 为 ? 对 Initializer 求值。
      2. v 设为 ? GetValue(defaultValue)。
  5. 执行 ? PutValue(lRef, v)。
  6. 返回 « propertyName »。
AssignmentProperty : PropertyName : AssignmentElement
  1. name 为 ? 对 PropertyName 求值。
  2. 执行 ? 对 AssignmentElement 执行 KeyedDestructuringAssignmentEvaluation,并以 valuename 为参数。
  3. 返回 « name »。

13.15.5.4 Runtime Semantics: RestDestructuringAssignmentEvaluation

The syntax-directed operation RestDestructuringAssignmentEvaluation takes arguments value (一个 ECMAScript 语言值) and excludedNames (一个属性键列表) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成. It is defined piecewise over the following productions:

AssignmentRestProperty : ... DestructuringAssignmentTarget
  1. lRef 为 ? 对 DestructuringAssignmentTarget 求值。
  2. restObjOrdinaryObjectCreate(%Object.prototype%)。
  3. 执行 ? CopyDataProperties(restObj, value, excludedNames)。
  4. 返回 ? PutValue(lRef, restObj)。

13.15.5.5 Runtime Semantics: IteratorDestructuringAssignmentEvaluation

The syntax-directed operation IteratorDestructuringAssignmentEvaluation takes argument iteratorRecord (一个 Iterator Record) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成. It is defined piecewise over the following productions:

AssignmentElementList : AssignmentElisionElement
  1. 返回 ? 对 AssignmentElisionElement 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
AssignmentElementList : AssignmentElementList , AssignmentElisionElement
  1. 执行 ? 对 AssignmentElementList 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
  2. 返回 ? 对 AssignmentElisionElement 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
AssignmentElisionElement : AssignmentElement
  1. 返回 ? 对 AssignmentElement 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
AssignmentElisionElement : Elision AssignmentElement
  1. 执行 ? 对 Elision 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
  2. 返回 ? 对 AssignmentElement 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
Elision : ,
  1. 如果 iteratorRecord.[[Done]]false,那么
    1. 执行 ? IteratorStep(iteratorRecord)。
  2. 返回 unused
Elision : Elision ,
  1. 执行 ? 对 Elision 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
  2. 如果 iteratorRecord.[[Done]]false,那么
    1. 执行 ? IteratorStep(iteratorRecord)。
  3. 返回 unused
AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,那么
    1. lRef 为 ? 对 DestructuringAssignmentTarget 求值。
  2. valueundefined
  3. 如果 iteratorRecord.[[Done]]false,那么
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不为 done,那么
      1. value 设为 next
  4. 如果 Initializer 存在且 valueundefined,那么
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 为 trueIsIdentifierRef of DestructuringAssignmentTargettrue,那么
      1. targetDestructuringAssignmentTargetStringValue
      2. v 为 ? 对 Initializer 执行 NamedEvaluation,并以 target 为参数。
    2. 否则,
      1. defaultValue 为 ? 对 Initializer 求值。
      2. v 为 ? GetValue(defaultValue)。
  5. 否则,
    1. vvalue
  6. 如果 DestructuringAssignmentTarget 是一个 ObjectLiteral 或一个 ArrayLiteral,那么
    1. nestedAssignmentPattern 为被 DestructuringAssignmentTarget 覆盖AssignmentPattern
    2. 返回 ? 对 nestedAssignmentPattern 执行 DestructuringAssignmentEvaluation,并以 v 为参数。
  7. 返回 ? PutValue(lRef, v)。
Note

从左到右的求值顺序通过如下方式得到保持:对于不是解构模式的 DestructuringAssignmentTarget,会在访问迭代器或对 Initializer 求值之前先对其求值。

AssignmentRestElement : ... DestructuringAssignmentTarget
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,那么
    1. lRef 为 ? 对 DestructuringAssignmentTarget 求值。
  2. array 为 ! ArrayCreate(0)。
  3. n 为 0。
  4. 重复,当 iteratorRecord.[[Done]]false 时,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不为 done,那么
      1. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), next)。
      2. n 设为 n + 1。
  5. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,那么
    1. 返回 ? PutValue(lRef, array)。
  6. nestedAssignmentPattern 为被 DestructuringAssignmentTarget 覆盖AssignmentPattern
  7. 返回 ? 对 nestedAssignmentPattern 执行 DestructuringAssignmentEvaluation,并以 array 为参数。

13.15.5.6 Runtime Semantics: KeyedDestructuringAssignmentEvaluation

The syntax-directed operation KeyedDestructuringAssignmentEvaluation takes arguments value (一个 ECMAScript 语言值) and propertyName (一个属性键) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成. It is defined piecewise over the following productions:

AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,那么
    1. lRef 为 ? 对 DestructuringAssignmentTarget 求值。
  2. v 为 ? GetV(value, propertyName)。
  3. 如果 Initializer 存在且 vundefined,那么
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 为 trueIsIdentifierRef of DestructuringAssignmentTargettrue,那么
      1. targetDestructuringAssignmentTargetStringValue
      2. rhsValue 为 ? 对 Initializer 执行 NamedEvaluation,并以 target 为参数。
    2. 否则,
      1. defaultValue 为 ? 对 Initializer 求值。
      2. rhsValue 为 ? GetValue(defaultValue)。
  4. 否则,
    1. rhsValuev
  5. 如果 DestructuringAssignmentTarget 是一个 ObjectLiteral 或一个 ArrayLiteral,那么
    1. assignmentPattern 为被 DestructuringAssignmentTarget 覆盖AssignmentPattern
    2. 返回 ? 对 assignmentPattern 执行 DestructuringAssignmentEvaluation,并以 rhsValue 为参数。
  6. 返回 ? PutValue(lRef, rhsValue)。

13.16 逗号运算符 ( , )

语法

Expression[In, Yield, Await] : AssignmentExpression[?In, ?Yield, ?Await] Expression[?In, ?Yield, ?Await] , AssignmentExpression[?In, ?Yield, ?Await]

13.16.1 Runtime Semantics: 求值

Expression : Expression , AssignmentExpression
  1. lRef 为 ? 对 Expression 求值。
  2. 执行 ? GetValue(lRef)。
  3. rRef 为 ? 对 AssignmentExpression 求值。
  4. 返回 ? GetValue(rRef)。
Note

即使不会使用其值,也必须调用 GetValue,因为它可能具有可观察的副作用。