14 ECMAScript 语言:语句和声明

语法

Statement[Yield, Await, Return] : BlockStatement[?Yield, ?Await, ?Return] VariableStatement[?Yield, ?Await] EmptyStatement ExpressionStatement[?Yield, ?Await] IfStatement[?Yield, ?Await, ?Return] BreakableStatement[?Yield, ?Await, ?Return] ContinueStatement[?Yield, ?Await] BreakStatement[?Yield, ?Await] [+Return] ReturnStatement[?Yield, ?Await] WithStatement[?Yield, ?Await, ?Return] LabelledStatement[?Yield, ?Await, ?Return] ThrowStatement[?Yield, ?Await] TryStatement[?Yield, ?Await, ?Return] DebuggerStatement Declaration[Yield, Await] : HoistableDeclaration[?Yield, ?Await, ~Default] ClassDeclaration[?Yield, ?Await, ~Default] LexicalDeclaration[+In, ?Yield, ?Await] HoistableDeclaration[Yield, Await, Default] : FunctionDeclaration[?Yield, ?Await, ?Default] GeneratorDeclaration[?Yield, ?Await, ?Default] AsyncFunctionDeclaration[?Yield, ?Await, ?Default] AsyncGeneratorDeclaration[?Yield, ?Await, ?Default] BreakableStatement[Yield, Await, Return] : IterationStatement[?Yield, ?Await, ?Return] SwitchStatement[?Yield, ?Await, ?Return]

14.1 语句语义

14.1.1 Runtime Semantics: 求值

HoistableDeclaration : GeneratorDeclaration AsyncFunctionDeclaration AsyncGeneratorDeclaration
  1. 返回 empty
HoistableDeclaration : FunctionDeclaration
  1. 返回 ? 对 FunctionDeclaration 求值。
BreakableStatement : IterationStatement SwitchStatement
  1. newLabelSet 为一个新的空列表。
  2. 返回 ? 对该 BreakableStatement 执行 LabelledEvaluation,并以 newLabelSet 为参数。

14.2

语法

BlockStatement[Yield, Await, Return] : Block[?Yield, ?Await, ?Return] Block[Yield, Await, Return] : { StatementList[?Yield, ?Await, ?Return]opt } StatementList[Yield, Await, Return] : StatementListItem[?Yield, ?Await, ?Return] StatementList[?Yield, ?Await, ?Return] StatementListItem[?Yield, ?Await, ?Return] StatementListItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] Declaration[?Yield, ?Await]

14.2.1 Static Semantics: 早期错误

Block : { StatementList }

14.2.2 Runtime Semantics: 求值

Block : { }
  1. 返回 empty
Block : { StatementList }
  1. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  2. blockEnvNewDeclarativeEnvironment(oldEnv)。
  3. 执行 BlockDeclarationInstantiation(StatementList, blockEnv)。
  4. 将当前运行执行上下文的 LexicalEnvironment 设为 blockEnv
  5. blockValueCompletion(对 StatementList 求值)。
  6. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
  7. 返回 ? blockValue
Note 1

无论控制以何种方式离开 Block,LexicalEnvironment 总是会恢复到其原先状态。

StatementList : StatementList StatementListItem
  1. sl 为 ? 对 StatementList 求值。
  2. sCompletion(对 StatementListItem 求值)。
  3. 返回 ? UpdateEmpty(s, sl)。
Note 2

StatementList 的值是该 StatementList 中最后一个产生值的项的值。 例如,以下对 eval 函数的调用都返回值 1:

eval("1;;;;;")
eval("1;{}")
eval("1;var a;")

14.2.3 BlockDeclarationInstantiation ( code, env )

The abstract operation BlockDeclarationInstantiation takes arguments code (一个 Parse Node) and env (一个 Declarative Environment Record) and returns unused. code 是对应于块体的 Parse Node。env 是要在其中创建绑定的 Environment Record

Note

当对一个 BlockCaseBlock 求值时,会创建一个新的 Declarative Environment Record,并且块中声明的每个块作用域变量、常量、函数或类的绑 定都会在该 Environment Record 中实例化。

被调用时它执行以下步骤:

  1. declarationscodeLexicallyScopedDeclarations
  2. privateEnv 为当前运行执行上下文的 PrivateEnvironment。
  3. 对于 declarations 中的每个元素 decl,执行
    1. 对于 declBoundNames 中的每个元素 dn,执行
      1. 如果 declIsConstantDeclarationtrue,那么
        1. 执行 ! env.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. Normative Optional
          如果宿主是 Web 浏览器或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,那么
          1. 如果 ! env.HasBinding(dn) 为 false,那么
            1. 执行 ! env.CreateMutableBinding(dn, false)。
        2. 否则,
          1. 执行 ! env.CreateMutableBinding(dn, false)。
    2. 如果 declFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration 之一,那么
      1. fndeclBoundNames 的唯一元素。
      2. fo 为对 decl 执行 InstantiateFunctionObject,并以 envprivateEnv 为参数。
      3. Normative Optional
        如果宿主是 Web 浏览器或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,那么
        1. 如果 envfn 的绑定是一个未初始化绑定,那么
          1. 执行 ! env.InitializeBinding(fn, fo)。
        2. 否则,
          1. 断言:decl 是一个 FunctionDeclaration
          2. 执行 ! env.SetMutableBinding(fn, fo, false)。
      4. 否则,
        1. 执行 ! env.InitializeBinding(fn, fo)。
  4. 返回 unused

14.3 声明与变量语句

14.3.1 Let 和 Const 声明

Note

letconst 声明定义的是作用域限于当前运行执行上下文的 LexicalEnvironment 的变量。这些变量在其所在的 Environment Record 实例 化时被创建,但在该变量的 LexicalBinding 被求值之前,不能以任何方式访 问。由带有 InitializerLexicalBinding 所定义的变量,会在 LexicalBinding 被求值时被赋予其 InitializerAssignmentExpression 的值,而不是在变量创建时赋值。如果 let 声明中 的某个 LexicalBinding 没有 Initializer,那么在该 LexicalBinding 被求值时,该变量会被赋值为 undefined

语法

LexicalDeclaration[In, Yield, Await] : LetOrConst BindingList[?In, ?Yield, ?Await] ; LetOrConst : let const BindingList[In, Yield, Await] : LexicalBinding[?In, ?Yield, ?Await] BindingList[?In, ?Yield, ?Await] , LexicalBinding[?In, ?Yield, ?Await] LexicalBinding[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]

14.3.1.1 Static Semantics: 早期错误

LexicalDeclaration : LetOrConst BindingList ; LexicalBinding : BindingIdentifier Initializeropt

14.3.1.2 Runtime Semantics: 求值

LexicalDeclaration : LetOrConst BindingList ;
  1. 执行 ? 对 BindingList 求值。
  2. 返回 empty
BindingList : BindingList , LexicalBinding
  1. 执行 ? 对 BindingList 求值。
  2. 返回 ? 对 LexicalBinding 求值。
LexicalBinding : BindingIdentifier
  1. lhs 为 ! ResolveBinding(StringValue of BindingIdentifier)。
  2. 执行 ! InitializeReferencedBinding(lhs, undefined)。
  3. 返回 empty
Note

一条静态语义规则保证这种形式的 LexicalBinding 永远不会出现在 const 声明中。

LexicalBinding : BindingIdentifier Initializer
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ! ResolveBinding(bindingId)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 为 true,那么
    1. value 为 ? 对 Initializer 执行 NamedEvaluation,并以 bindingId 为参数。
  4. 否则,
    1. rhs 为 ? 对 Initializer 求值。
    2. value 为 ? GetValue(rhs)。
  5. 执行 ! InitializeReferencedBinding(lhs, value)。
  6. 返回 empty
LexicalBinding : BindingPattern Initializer
  1. rhs 为 ? 对 Initializer 求值。
  2. value 为 ? GetValue(rhs)。
  3. env 为当前运行执行上下文的 LexicalEnvironment。
  4. 返回 ? 对 BindingPattern 执行 BindingInitialization,并以 valueenv 为参数。

14.3.2 变量语句

Note

var 语句声明的是作用域限于当前运行执行上下文的 VariableEnvironment 的变量。var 变量在其所在的 Environment Record 实例 化时被创建,并在创建时初始化为 undefined。在任意 VariableEnvironment 的作用域内,同一个 BindingIdentifier 可以出现在 多个 VariableDeclaration 中,但这些声明共同只定义一个变量。由带有 InitializerVariableDeclaration 所定义的变量,会在该 VariableDeclaration 执行时被赋予其 InitializerAssignmentExpression 的值,而不是在变量创建时赋值。

语法

VariableStatement[Yield, Await] : var VariableDeclarationList[+In, ?Yield, ?Await] ; VariableDeclarationList[In, Yield, Await] : VariableDeclaration[?In, ?Yield, ?Await] VariableDeclarationList[?In, ?Yield, ?Await] , VariableDeclaration[?In, ?Yield, ?Await] VariableDeclaration[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]

14.3.2.1 Runtime Semantics: 求值

VariableStatement : var VariableDeclarationList ;
  1. 执行 ? 对 VariableDeclarationList 求值。
  2. 返回 empty
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. 执行 ? 对 VariableDeclarationList 求值。
  2. 返回 ? 对 VariableDeclaration 求值。
VariableDeclaration : BindingIdentifier
  1. 返回 empty
VariableDeclaration : BindingIdentifier Initializer
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingId)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 为 true,那么
    1. value 为 ? 对 Initializer 执行 NamedEvaluation,并以 bindingId 为参数。
  4. 否则,
    1. rhs 为 ? 对 Initializer 求值。
    2. value 为 ? GetValue(rhs)。
  5. 执行 ? PutValue(lhs, value)。
  6. 返回 empty
Note

如果某个 VariableDeclaration 嵌套在一个 with 语句内部,并且该 VariableDeclaration 中的 BindingIdentifier 与该 with 语句的对象 环境记录的绑定对象的某个属性名相同,那么步骤 5 会将 value 赋给该属性,而不是赋给 Identifier 的 VariableEnvironment 绑定。

VariableDeclaration : BindingPattern Initializer
  1. rhs 为 ? 对 Initializer 求值。
  2. rVal 为 ? GetValue(rhs)。
  3. 返回 ? 对 BindingPattern 执行 BindingInitialization,并以 rValundefined 为参数。

14.3.3 解构绑定模式

语法

BindingPattern[Yield, Await] : ObjectBindingPattern[?Yield, ?Await] ArrayBindingPattern[?Yield, ?Await] ObjectBindingPattern[Yield, Await] : { } { BindingRestProperty[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] , BindingRestProperty[?Yield, ?Await]opt } ArrayBindingPattern[Yield, Await] : [ Elisionopt BindingRestElement[?Yield, ?Await]opt ] [ BindingElementList[?Yield, ?Await] ] [ BindingElementList[?Yield, ?Await] , Elisionopt BindingRestElement[?Yield, ?Await]opt ] BindingRestProperty[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] BindingPropertyList[Yield, Await] : BindingProperty[?Yield, ?Await] BindingPropertyList[?Yield, ?Await] , BindingProperty[?Yield, ?Await] BindingElementList[Yield, Await] : BindingElisionElement[?Yield, ?Await] BindingElementList[?Yield, ?Await] , BindingElisionElement[?Yield, ?Await] BindingElisionElement[Yield, Await] : Elisionopt BindingElement[?Yield, ?Await] BindingProperty[Yield, Await] : SingleNameBinding[?Yield, ?Await] PropertyName[?Yield, ?Await] : BindingElement[?Yield, ?Await] BindingElement[Yield, Await] : SingleNameBinding[?Yield, ?Await] BindingPattern[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt SingleNameBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt BindingRestElement[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] ... BindingPattern[?Yield, ?Await]

14.3.3.1 Runtime Semantics: PropertyBindingInitialization

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

BindingPropertyList : BindingPropertyList , BindingProperty
  1. boundNames 为 ? 对 BindingPropertyList 执行 PropertyBindingInitialization,并以 valueenvironment 为参 数。
  2. nextNames 为 ? 对 BindingProperty 执行 PropertyBindingInitialization,并以 valueenvironment 为参 数。
  3. 返回 boundNamesnextNames 的列表串接。
BindingProperty : SingleNameBinding
  1. nameSingleNameBindingBoundNames 的唯一元素。
  2. 执行 ? 对 SingleNameBinding 执行 KeyedBindingInitialization, 并以 valueenvironmentname 为参数。
  3. 返回 « name »。
BindingProperty : PropertyName : BindingElement
  1. propertyKey 为 ? 对 PropertyName 求值。
  2. 执行 ? 对 BindingElement 执行 KeyedBindingInitialization,并以 valueenvironmentpropertyKey 为参数。
  3. 返回 « propertyKey »。

14.3.3.2 Runtime Semantics: RestBindingInitialization

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

BindingRestProperty : ... BindingIdentifier
  1. lhs 为 ? ResolveBinding(StringValue of BindingIdentifier, environment)。
  2. restObjOrdinaryObjectCreate(%Object.prototype%)。
  3. 执行 ? CopyDataProperties(restObj, value, excludedNames)。
  4. 如果 environmentundefined,返回 ? PutValue(lhs, restObj)。
  5. 返回 ? InitializeReferencedBinding(lhs, restObj)。

14.3.3.3 Runtime Semantics: KeyedBindingInitialization

The syntax-directed operation KeyedBindingInitialization takes arguments value (一个 ECMAScript 语言值), environment (一个 Environment Recordundefined), and propertyName (一个属性键) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成.

Note

environment 传入 undefined 时,表示应当使用 PutValue 操作 来赋予初始化值。这种情况出现在非严格函数的形式参数列表中。在那种情况下, 形式参数绑定会被预初始化,以处理多个参数具有相同名称的可能性。

It is defined piecewise over the following productions:

BindingElement : BindingPattern Initializeropt
  1. v 为 ? GetV(value, propertyName)。
  2. 如果 Initializer 存在且 vundefined,那么
    1. defaultValue 为 ? 对 Initializer 求值。
    2. v 设为 ? GetValue(defaultValue)。
  3. 返回 ? 对 BindingPattern 执行 BindingInitialization,并以 venvironment 为参数。
SingleNameBinding : BindingIdentifier Initializeropt
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingId, environment)。
  3. v 为 ? GetV(value, propertyName)。
  4. 如果 Initializer 存在且 vundefined,那么
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 为 true,那么
      1. v 设为 ? 对 Initializer 执行 NamedEvaluation,并以 bindingId 为参数。
    2. 否则,
      1. defaultValue 为 ? 对 Initializer 求值。
      2. v 设为 ? GetValue(defaultValue)。
  5. 如果 environmentundefined,返回 ? PutValue(lhs, v)。
  6. 返回 ? InitializeReferencedBinding(lhs, v)。

14.4 空语句

语法

EmptyStatement : ;

14.4.1 Runtime Semantics: 求值

EmptyStatement : ;
  1. 返回 empty

14.5 表达式语句

语法

ExpressionStatement[Yield, Await] : [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }] Expression[+In, ?Yield, ?Await] ; Note

ExpressionStatement 不能以 U+007B(LEFT CURLY BRACKET)开头, 因为那会使它与 Block 产生歧义。ExpressionStatement 不能以关键字 functionclass 开头,因为那会使它与 FunctionDeclarationGeneratorDeclarationClassDeclaration 产生歧义。 ExpressionStatement 不能以 async function 开头,因为那会使它与 AsyncFunctionDeclarationAsyncGeneratorDeclaration 产生歧义。 ExpressionStatement 不能以两个记号序列 let [ 开头,因为那会使它与一 个 let LexicalDeclaration 产生歧义,而该声明的第一个 LexicalBinding 是一个 ArrayBindingPattern

14.5.1 Runtime Semantics: 求值

ExpressionStatement : Expression ;
  1. exprRef 为 ? 对 Expression 求值。
  2. 返回 ? GetValue(exprRef)。

14.6 if 语句

语法

IfStatement[Yield, Await, Return] : if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] else Statement[?Yield, ?Await, ?Return] if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [lookahead ≠ else] Note
[lookahead ≠ else] 这一前瞻限制以通常方式解决了经典的“悬空 else”问题。也就是说,当关联哪个 if 在其他方面仍然有歧义时,else 会与候选 if 中最近的(最内层的)那个相关联。

14.6.1 Static Semantics: 早期错误

IfStatement : if ( Expression ) Statement else Statement IfStatement : if ( Expression ) Statement Note

仅在实现了 B.3.1 中规定的扩展时,才有必要应用此规则。

14.6.2 Runtime Semantics: 求值

IfStatement : if ( Expression ) Statement else Statement
  1. exprRef 为 ? 对 Expression 求值。
  2. exprValueToBoolean(? GetValue(exprRef))。
  3. 如果 exprValuetrue,那么
    1. stmtCompletionCompletion(对第一个 Statement 求值)。
  4. 否则,
    1. stmtCompletionCompletion(对第二个 Statement 求值)。
  5. 返回 ? UpdateEmpty(stmtCompletion, undefined)。
IfStatement : if ( Expression ) Statement
  1. exprRef 为 ? 对 Expression 求值。
  2. exprValueToBoolean(? GetValue(exprRef))。
  3. 如果 exprValuefalse,返回 undefined
  4. stmtCompletionCompletion(对 Statement 求值)。
  5. 返回 ? UpdateEmpty(stmtCompletion, undefined)。

14.7 迭代语句

语法

IterationStatement[Yield, Await, Return] : DoWhileStatement[?Yield, ?Await, ?Return] WhileStatement[?Yield, ?Await, ?Return] ForStatement[?Yield, ?Await, ?Return] ForInOfStatement[?Yield, ?Await, ?Return]

14.7.1 语义

14.7.1.1 LoopContinues ( completion, labelSet )

The abstract operation LoopContinues takes arguments completion (一个 Completion Record) and labelSet (一个 String 列表) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 completion 是一个正常完成,返回 true
  2. 如果 completion 不是一个 continue 完成,返回 false
  3. 如果 completion.[[Target]]empty,返回 true
  4. 如果 labelSet 包含 completion.[[Target]],返回 true
  5. 返回 false
Note

IterationStatementStatement 部分内部,可以使用 ContinueStatement 来开始一次新的迭代。

14.7.1.2 Runtime Semantics: LoopEvaluation

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

IterationStatement : DoWhileStatement
  1. 返回 ? 对 DoWhileStatement 执行 DoWhileLoopEvaluation,并以 labelSet 为参数。
IterationStatement : WhileStatement
  1. 返回 ? 对 WhileStatement 执行 WhileLoopEvaluation,并以 labelSet 为参数。
IterationStatement : ForStatement
  1. 返回 ? 对 ForStatement 执行 ForLoopEvaluation,并以 labelSet 为参数。
IterationStatement : ForInOfStatement
  1. 返回 ? 对 ForInOfStatement 执行 ForInOfLoopEvaluation,并以 labelSet 为参数。

14.7.2 do-while 语句

语法

DoWhileStatement[Yield, Await, Return] : do Statement[?Yield, ?Await, ?Return] while ( Expression[+In, ?Yield, ?Await] ) ;

14.7.2.1 Static Semantics: 早期错误

DoWhileStatement : do Statement while ( Expression ) ; Note

仅在实现了 B.3.1 中规定的扩展时,才有必要应用此规则。

14.7.2.2 Runtime Semantics: DoWhileLoopEvaluation

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

DoWhileStatement : do Statement while ( Expression ) ;
  1. iterationResultundefined
  2. 重复,
    1. stmtResultCompletion(对 Statement 求值)。
    2. 如果 LoopContinues(stmtResult, labelSet) 为 false,返回 ? UpdateEmpty(stmtResult, iterationResult)。
    3. 如果 stmtResult.[[Value]] 不为 empty,将 iterationResult 设为 stmtResult.[[Value]]
    4. exprRef 为 ? 对 Expression 求值。
    5. exprValue 为 ? GetValue(exprRef)。
    6. 如果 ToBoolean(exprValue) 为 false,返回 iterationResult

14.7.3 while 语句

语法

WhileStatement[Yield, Await, Return] : while ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return]

14.7.3.1 Static Semantics: 早期错误

WhileStatement : while ( Expression ) Statement Note

仅在实现了 B.3.1 中规定的扩展时,才有必要应用此规则。

14.7.3.2 Runtime Semantics: WhileLoopEvaluation

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

WhileStatement : while ( Expression ) Statement
  1. iterationResultundefined
  2. 重复,
    1. exprRef 为 ? 对 Expression 求值。
    2. exprValue 为 ? GetValue(exprRef)。
    3. 如果 ToBoolean(exprValue) 为 false,返回 iterationResult
    4. stmtResultCompletion(对 Statement 求值)。
    5. 如果 LoopContinues(stmtResult, labelSet) 为 false,返回 ? UpdateEmpty(stmtResult, iterationResult)。
    6. 如果 stmtResult.[[Value]] 不为 empty,将 iterationResult 设为 stmtResult.[[Value]]

14.7.4 for 语句

语法

ForStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] Expression[~In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( var VariableDeclarationList[~In, ?Yield, ?Await] ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( LexicalDeclaration[~In, ?Yield, ?Await] Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return]

14.7.4.1 Static Semantics: 早期错误

ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement Note

仅在实现了 B.3.1 中规定的扩展时,才有必要应用此规则。

ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

14.7.4.2 Runtime Semantics: ForLoopEvaluation

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

ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement
  1. 如果第一个 Expression 存在,那么
    1. exprRef 为 ? 对第一个 Expression 求值。
    2. 执行 ? GetValue(exprRef)。
  2. 如果第二个 Expression 存在,令 test 为第二个 Expression; 否则令 testempty
  3. 如果第三个 Expression 存在,令 increment 为第三个 Expression;否则令 incrementempty
  4. 返回 ? ForBodyEvaluation(test, increment, Statement, « », labelSet)。
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. 执行 ? 对 VariableDeclarationList 求值。
  2. 如果第一个 Expression 存在,令 test 为第一个 Expression; 否则令 testempty
  3. 如果第二个 Expression 存在,令 increment 为第二个 Expression;否则令 incrementempty
  4. 返回 ? ForBodyEvaluation(test, increment, Statement, « », labelSet)。
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  2. loopEnvNewDeclarativeEnvironment(oldEnv)。
  3. isConstLexicalDeclarationIsConstantDeclaration
  4. boundNamesLexicalDeclarationBoundNames
  5. 对于 boundNames 中的每个元素 dn,执行
    1. 如果 isConsttrue,那么
      1. 执行 ! loopEnv.CreateImmutableBinding(dn, true)。
    2. 否则,
      1. 执行 ! loopEnv.CreateMutableBinding(dn, false)。
  6. 将当前运行执行上下文的 LexicalEnvironment 设为 loopEnv
  7. forDclCompletion(对 LexicalDeclaration 求值)。
  8. 如果 forDcl 是一个突然完成,那么
    1. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
    2. 返回 ? forDcl
  9. 如果 isConstfalse,令 perIterationLetsboundNames; 否则令 perIterationLets 为一个新的空列表。
  10. 如果第一个 Expression 存在,令 test 为第一个 Expression; 否则令 testempty
  11. 如果第二个 Expression 存在,令 increment 为第二个 Expression;否则令 incrementempty
  12. bodyResultCompletion(ForBodyEvaluation(test, increment, Statement, perIterationLets, labelSet))。
  13. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
  14. 返回 ? bodyResult

14.7.4.3 ForBodyEvaluation ( test, increment, stmt, perIterationBindings, labelSet )

The abstract operation ForBodyEvaluation takes arguments test (一个 Expression Parse Node 或 empty), increment (一个 Expression Parse Node 或 empty), stmt (一个 Statement Parse Node), perIterationBindings (一个 String 列表), and labelSet (一个 String 列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个突然完成. It performs the following steps when called:

  1. iterationResultundefined
  2. 执行 ? CreatePerIterationEnvironment(perIterationBindings)。
  3. 重复,
    1. 如果 test 不为 empty,那么
      1. testRef 为 ? 对 test 求值。
      2. testValue 为 ? GetValue(testRef)。
      3. 如果 ToBoolean(testValue) 为 false,返回 iterationResult
    2. resultCompletion(对 stmt 求值)。
    3. 如果 LoopContinues(result, labelSet) 为 false,返回 ? UpdateEmpty(result, iterationResult)。
    4. 如果 result.[[Value]] 不为 empty,将 iterationResult 设为 result.[[Value]]
    5. 执行 ? CreatePerIterationEnvironment(perIterationBindings)。
    6. 如果 increment 不为 empty,那么
      1. incRef 为 ? 对 increment 求值。
      2. 执行 ? GetValue(incRef)。

14.7.4.4 CreatePerIterationEnvironment ( perIterationBindings )

The abstract operation CreatePerIterationEnvironment takes argument perIterationBindings (一个 String 列表) and returns 要么是一个正常完成,包含 unused,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 perIterationBindings 含有任何元素,那么
    1. lastIterationEnv 为当前运行执行上下文的 LexicalEnvironment。
    2. outerlastIterationEnv.[[OuterEnv]]
    3. 断言:outer 不为 null
    4. thisIterationEnvNewDeclarativeEnvironment(outer)。
    5. 对于 perIterationBindings 中的每个元素 bn,执行
      1. 执行 ! thisIterationEnv.CreateMutableBinding(bn, false)。
      2. lastValue 为 ? lastIterationEnv.GetBindingValue(bn, true)。
      3. 执行 ! thisIterationEnv.InitializeBinding(bn, lastValue)。
    6. 将当前运行执行上下文的 LexicalEnvironment 设为 thisIterationEnv
  2. 返回 unused

14.7.5 for-infor-offor-await-of 语句

语法

ForInOfStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] LeftHandSideExpression[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( [lookahead ∉ { let, async of }] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( [lookahead ≠ let] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( var ForBinding[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] ForDeclaration[Yield, Await] : LetOrConst ForBinding[?Yield, ?Await] ForBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await] Note

本节由附录 B.3.5 扩展。

14.7.5.1 Static Semantics: 早期错误

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement Note

仅在实现了 B.3.1 中规定的扩展时,才有必要应用此规则。

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement ForInOfStatement : for ( ForDeclaration in Expression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement

14.7.5.2 Static Semantics: IsDestructuring

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

MemberExpression : PrimaryExpression
  1. 如果 PrimaryExpression 是一个 ObjectLiteral 或一个 ArrayLiteral,返回 true
  2. 返回 false
MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName MemberExpression TemplateLiteral SuperProperty MetaProperty new MemberExpression Arguments MemberExpression . PrivateIdentifier NewExpression : new NewExpression LeftHandSideExpression : CallExpression OptionalExpression
  1. 返回 false
ForDeclaration : LetOrConst ForBinding
  1. 返回 ForBindingIsDestructuring
ForBinding : BindingIdentifier
  1. 返回 false
ForBinding : BindingPattern
  1. 返回 true
Note

本节由附录 B.3.5 扩展。

14.7.5.3 Runtime Semantics: ForDeclarationBindingInitialization

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

ForDeclaration : LetOrConst ForBinding
  1. 返回 ? 对 ForBinding 执行 BindingInitialization,并以 valueenvironment 为参数。

14.7.5.4 Runtime Semantics: ForDeclarationBindingInstantiation

The syntax-directed operation ForDeclarationBindingInstantiation takes argument environment (一个 Declarative Environment Record) and returns unused. It is defined piecewise over the following productions:

ForDeclaration : LetOrConst ForBinding
  1. 对于 ForBindingBoundNames 中的每个元素 name,执行
    1. 如果 LetOrConstIsConstantDeclarationtrue,那么
      1. 执行 ! environment.CreateImmutableBinding(name, true)。
    2. 否则,
      1. 执行 ! environment.CreateMutableBinding(name, false)。
  2. 返回 unused

14.7.5.5 Runtime Semantics: ForInOfLoopEvaluation

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

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, enumerate, assignment, labelSet)。
ForInOfStatement : for ( var ForBinding in Expression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, enumerate, var-binding, labelSet)。
ForInOfStatement : for ( ForDeclaration in Expression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, enumerate, lexical-binding, labelSet)。
ForInOfStatement : for ( LeftHandSideExpression of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, iterate, assignment, labelSet)。
ForInOfStatement : for ( var ForBinding of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, iterate, var-binding, labelSet)。
ForInOfStatement : for ( ForDeclaration of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, AssignmentExpression, iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexical-binding, labelSet)。
ForInOfStatement : for await ( LeftHandSideExpression of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, async-iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, iterate, assignment, labelSet, async)。
ForInOfStatement : for await ( var ForBinding of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, async-iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, iterate, var-binding, labelSet, async)。
ForInOfStatement : for await ( ForDeclaration of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, AssignmentExpression, async-iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexical-binding, labelSet, async)。
Note

本节由附录 B.3.5 扩展。

14.7.5.6 ForIn/OfHeadEvaluation ( uninitializedBoundNames, expr, iterationKind )

The abstract operation ForIn/OfHeadEvaluation takes arguments uninitializedBoundNames (一个 String 列表), expr (一个 Expression Parse Node 或一个 AssignmentExpression Parse Node), and iterationKind (enumerateiterateasync-iterate) and returns 要么是一个正常完成,包含一个 Iterator Record,要么是一个突然完成. It performs the following steps when called:

  1. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  2. 如果 uninitializedBoundNames 非空,那么
    1. 断言:uninitializedBoundNames 不含重复条目。
    2. newEnvNewDeclarativeEnvironment(oldEnv)。
    3. 对于 uninitializedBoundNames 中的每个 String name,执行
      1. 执行 ! newEnv.CreateMutableBinding(name, false)。
    4. 将当前运行执行上下文的 LexicalEnvironment 设为 newEnv
  3. exprRefCompletion(对 expr 求值)。
  4. 将当前运行执行上下文的 LexicalEnvironment 设回 oldEnv
  5. exprValue 为 ? GetValue(? exprRef)。
  6. 如果 iterationKindenumerate,那么
    1. 如果 exprValueundefinednull,那么
      1. 返回 Completion Record { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }。
    2. obj 为 ! ToObject(exprValue)。
    3. iteratorEnumerateObjectProperties(obj)。
    4. nextMethod 为 ! GetV(iterator, "next")。
    5. 返回 Iterator Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }。
  7. 断言:iterationKinditerateasync-iterate 之一。
  8. 如果 iterationKindasync-iterate,令 iteratorKindasync
  9. 否则,令 iteratorKindsync
  10. 返回 ? GetIterator(exprValue, iteratorKind)。

14.7.5.7 ForIn/OfBodyEvaluation ( lhs, stmt, iteratorRecord, iterationKind, lhsKind, labelSet [ , iteratorKind ] )

The abstract operation ForIn/OfBodyEvaluation takes arguments lhs (一个 Parse Node), stmt (一个 Statement Parse Node), iteratorRecord (一个 Iterator Record), iterationKind (enumerateiterate), lhsKind (assignmentvar-bindinglexical-binding), and labelSet (一个 String 列表) and optional argument iteratorKind (syncasync) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个突然完成. It performs the following steps when called:

  1. 如果 iteratorKind 未出现,将 iteratorKind 设为 sync
  2. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  3. iterationResultundefined
  4. destructuringlhsIsDestructuring
  5. 如果 destructuringtruelhsKindassignment,那么
    1. 断言:lhs 是一个 LeftHandSideExpression
    2. assignmentPatternlhs覆盖AssignmentPattern
  6. 重复,
    1. nextResult 为 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]])。
    2. 如果 iteratorKindasync,将 nextResult 设为 ? Await(nextResult)。
    3. 如果 nextResult 不是一个 Object,抛出一个 TypeError 异常。
    4. done 为 ? IteratorComplete(nextResult)。
    5. 如果 donetrue,返回 iterationResult
    6. nextValue 为 ? IteratorValue(nextResult)。
    7. 如果 lhsKindassignmentvar-binding 之一,那么
      1. 如果 destructuringtrue,那么
        1. 如果 lhsKindassignment,那么
          1. statusCompletion(对 assignmentPattern 执行 DestructuringAssignmentEvaluation,并以 nextValue 为参数)。
        2. 否则,
          1. 断言:lhsKindvar-binding
          2. 断言:lhs 是一个 ForBinding
          3. statusCompletion(对 lhs 执行 BindingInitialization,并以 nextValueundefined 为参数)。
      2. 否则,
        1. lhsRefCompletion(对 lhs 求值)。(它可能会被重复求值。)
        2. 如果 lhsKindassignmentlhsAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
        3. 如果 lhsRef 是一个突然完成,那么
          1. statuslhsRef
        4. 否则,
          1. statusCompletion(PutValue(lhsRef.[[Value]], nextValue))。
    8. 否则,
      1. 断言:lhsKindlexical-binding
      2. 断言:lhs 是一个 ForDeclaration
      3. iterationEnvNewDeclarativeEnvironment(oldEnv)。
      4. 执行 ForDeclarationBindingInstantiation of lhs,并以 iterationEnv 为参数。
      5. 将当前运行执行上下文的 LexicalEnvironment 设为 iterationEnv
      6. 如果 destructuringtrue,那么
        1. statusCompletion(对 lhs 执行 ForDeclarationBindingInitialization,并以 nextValueiterationEnv 为参数)。
      7. 否则,
        1. 断言:lhs 绑定单个名称。
        2. lhsNamelhsBoundNames 的唯一元素。
        3. lhsRef 为 ! ResolveBinding(lhsName)。
        4. statusCompletion(InitializeReferencedBinding(lhsRef, nextValue))。
    9. 如果 status 是一个突然完成,那么
      1. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
      2. 如果 iterationKindenumerate,返回 ? status
      3. 断言:iterationKinditerate
      4. 如果 iteratorKindasync,返回 ? AsyncIteratorClose(iteratorRecord, status)。
      5. 返回 ? IteratorClose(iteratorRecord, status)。
    10. resultCompletion(对 stmt 求值)。
    11. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
    12. 如果 LoopContinues(result, labelSet) 为 false,那么
      1. status 设为 Completion(UpdateEmpty(result, iterationResult))。
      2. 如果 iterationKindenumerate,返回 ? status
      3. 断言:iterationKinditerate
      4. 如果 iteratorKindasync,返回 ? AsyncIteratorClose(iteratorRecord, status)。
      5. 返回 ? IteratorClose(iteratorRecord, status)。
    13. 如果 result.[[Value]] 不为 empty,将 iterationResult 设为 result.[[Value]]

14.7.5.8 Runtime Semantics: 求值

BindingIdentifier : Identifier yield await
  1. bindingIdBindingIdentifierStringValue
  2. 返回 ? ResolveBinding(bindingId)。

14.7.5.9 EnumerateObjectProperties ( obj )

The abstract operation EnumerateObjectProperties takes argument obj (一个 Object) and returns 一个迭代器对象. It performs the following steps when called:

  1. 返回一个迭代器对象,其 next 方法会遍历 obj 的所有可枚举属性中值为 String 的键。该迭代器对象永远不能被 ECMAScript 代码直接访问。枚举属性的机制与顺序未被规定,但必须符合下方规定的规则。

该迭代器的 throwreturn 方法为 null,并且永远不会被调用。该 迭代器的 next 方法会处理对象属性,以判定该属性键是否应作为迭代器值返回。 返回的属性键不包括 Symbol 键。在枚举期间,目标对象的属性可能会被删除。在 被迭代器的 next 方法处理之前就已被删除的属性会被忽略。如果在枚举期间向 目标对象新增属性,则不能保证这些新加属性会在当前激活的枚举中被处理。某个属 性名在任何一次枚举中,最多只会由迭代器的 next 方法返回一次。

对目标对象属性的枚举还包括递归枚举其原型、原型的原型,以此类推;但如果某 个原型上的属性与已被迭代器 next 方法处理过的某个属性同名,则不会处理该原 型属性。在判断某个原型对象的属性是否已被处理时,不考虑 [[Enumerable]] 特 性的值。原型对象的可枚举属性名必须通过调用 EnumerateObjectProperties 并将 该原型对象作为参数来获得。EnumerateObjectProperties 必须通过调用目标对象 的 [[OwnPropertyKeys]] 内部方法来获得其自有属性键。目标对象的属性特性必须 通过调用其 [[GetOwnProperty]] 内部方法来获得。

此外,如果 obj 及其原型链上的任何对象都不是 Proxy 异质对象TypedArray模块命名空间异质对象或实现提供的异质对象,那么该迭代器就必须 表现得像由 CreateForInIterator(obj) 所给出的迭代器一样,直到发生以下任 一情况为止:

  • obj 或其原型链中某个对象的 [[Prototype]] 内部槽的值发生变化,
  • obj 或其原型链中某个对象上移除了某个属性,
  • obj 的原型链中的某个对象添加了某个属性,或
  • obj 或其原型链中某个对象的某个属性的 [[Enumerable]] 特性的值发生变化。
Note 1

ECMAScript 实现不要求直接实现 14.7.5.10.2.1 中的算法。它们可以选择任何一种实现,只要其行为不会偏离该算法,除非违反了 前一段中的某项约束。

以下是一个符合这些规则的 ECMAScript 生成器函数的信息性定义:

function* EnumerateObjectProperties(obj) {
  const visited = new Set();
  for (const key of Reflect.ownKeys(obj)) {
    if (typeof key === "symbol") continue;
    const desc = Reflect.getOwnPropertyDescriptor(obj, key);
    if (desc) {
      visited.add(key);
      if (desc.enumerable) yield key;
    }
  }
  const proto = Reflect.getPrototypeOf(obj);
  if (proto === null) return;
  for (const protoKey of EnumerateObjectProperties(proto)) {
    if (!visited.has(protoKey)) yield protoKey;
  }
}
Note 2
实现不要求与 CreateForInIterator 保持一致的异质对象列表之所以如此选取, 是因为实现历史上在这些情形下的行为有所不同,而在其他所有情形下都一致。

14.7.5.10 For-In 迭代器对象

For-In 迭代器 是一种对象,它表示对某个特定对象进行的一次特定迭代。For-In 迭代器对象永远 不能被 ECMAScript 代码直接访问;它们的存在仅用于说明 EnumerateObjectProperties 的行为。

14.7.5.10.1 CreateForInIterator ( object )

The abstract operation CreateForInIterator takes argument object (一个 Object) and returns 一个 For-In 迭代器. 它用于创建一个 For-In 迭代器对象,该对象以特定顺序遍历 object 自有及继承的可枚举字符串属性。 It performs the following steps when called:

  1. iteratorOrdinaryObjectCreate(%ForInIteratorPrototype%, « [[Object]], [[ObjectWasVisited]], [[VisitedKeys]], [[RemainingKeys]] »)。
  2. iterator.[[Object]] 设为 object
  3. iterator.[[ObjectWasVisited]] 设为 false
  4. iterator.[[VisitedKeys]] 设为一个新的空列表。
  5. iterator.[[RemainingKeys]] 设为一个新的空列表。
  6. 返回 iterator

14.7.5.10.2 %ForInIteratorPrototype% 对象

%ForInIteratorPrototype% 对象:

14.7.5.10.2.1 %ForInIteratorPrototype%.next ( )

  1. iterthis 值。
  2. 断言:iter 是一个 Object。
  3. 断言:iter 具有 For-In 迭代器实例的全部内部槽(14.7.5.10.3)。
  4. objectiter.[[Object]]
  5. 重复,
    1. 如果 iter.[[ObjectWasVisited]]false,那么
      1. keys 为 ? object.[[OwnPropertyKeys]]()
      2. 对于 keys 中的每个元素 key,执行
        1. 如果 key 是一个 String,那么
          1. key 追加到 iter.[[RemainingKeys]]
      3. iter.[[ObjectWasVisited]] 设为 true
    2. 重复,当 iter.[[RemainingKeys]] 非空时,
      1. keyiter.[[RemainingKeys]] 的第一个元素。
      2. iter.[[RemainingKeys]] 中移除第一个元素。
      3. 如果 iter.[[VisitedKeys]] 不包含 key,那么
        1. desc 为 ? object.[[GetOwnProperty]](key)
        2. 如果 desc 不为 undefined,那么
          1. key 追加到 iter.[[VisitedKeys]]
          2. 如果 desc.[[Enumerable]]true,返回 CreateIteratorResultObject(key, false)。
    3. object 设为 ? object.[[GetPrototypeOf]]()
    4. iter.[[Object]] 设为 object
    5. iter.[[ObjectWasVisited]] 设为 false
    6. 如果 objectnull,返回 CreateIteratorResultObject(undefined, true)。

14.7.5.10.3 For-In 迭代器实例的属性

For-In 迭代器实例是普通对象,它们从内在对象 %ForInIteratorPrototype% 继承属性。For-In 迭代器实例在初始创建时具有 Table 33 中列出的内部槽。

Table 33: For-In 迭代器实例的内部槽
内部槽 类型 描述
[[Object]] 一个 Object 其属性正在被迭代的 Object 值。
[[ObjectWasVisited]] 一个 Boolean 如果迭代器已经对 [[Object]] 调用了 [[OwnPropertyKeys]], 则为 true;否则为 false
[[VisitedKeys]] 一个 String 列表 到目前为止该迭代器已经发出的值。
[[RemainingKeys]] 一个 String 列表 在开始迭代其原型的属性之前(如果其原型不为 null),当前对象还剩余待发出的值。

14.8 continue 语句

语法

ContinueStatement[Yield, Await] : continue ; continue [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ;

14.8.1 Static Semantics: 早期错误

ContinueStatement : continue ; continue LabelIdentifier ;

14.8.2 Runtime Semantics: 求值

ContinueStatement : continue ;
  1. 返回 Completion Record { [[Type]]: continue, [[Value]]: empty, [[Target]]: empty }。
ContinueStatement : continue LabelIdentifier ;
  1. labelLabelIdentifierStringValue
  2. 返回 Completion Record { [[Type]]: continue, [[Value]]: empty, [[Target]]: label }。

14.9 break 语句

语法

BreakStatement[Yield, Await] : break ; break [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ;

14.9.1 Static Semantics: 早期错误

BreakStatement : break ;

14.9.2 Runtime Semantics: 求值

BreakStatement : break ;
  1. 返回 Completion Record { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }。
BreakStatement : break LabelIdentifier ;
  1. labelLabelIdentifierStringValue
  2. 返回 Completion Record { [[Type]]: break, [[Value]]: empty, [[Target]]: label }。

14.10 return 语句

语法

ReturnStatement[Yield, Await] : return ; return [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; Note

return 语句会使函数停止执行,并且在大多数情况下会向调用者返回一个值。 如果省略 Expression,返回值是 undefined。否则,返回值就是 Expression 的值。根据外围上下文不同,return 语句实际上不一定真的向 调用者返回一个值。例如,在 try 块中,return 语句的 Completion Record 可能在 finally 块求值期间被另一个 Completion Record 替换。

14.10.1 Runtime Semantics: 求值

ReturnStatement : return ;
  1. 返回 ReturnCompletion(undefined)。
ReturnStatement : return Expression ;
  1. exprRef 为 ? 对 Expression 求值。
  2. exprValue 为 ? GetValue(exprRef)。
  3. 如果 GetGeneratorKind() 为 async,将 exprValue 设为 ? Await(exprValue)。
  4. 返回 ReturnCompletion(exprValue)。
Legacy

14.11 with 语句

Note 1

不鼓励在新的 ECMAScript 代码中使用这种遗留with 语句。请考虑在严 格模式代码和非严格代码中都允许的替代方案,例如 解构赋值

语法

WithStatement[Yield, Await, Return] : with ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] Note 2

with 语句会为一个计算得出的对象向当前运行执行上下文的词法环境中添加 一个对象环境记录。然后它使用这个增强后的词法环境执行一条语句。最后,它恢复 原始词法环境。

14.11.1 Static Semantics: 早期错误

WithStatement : with ( Expression ) Statement Note

仅在实现了 B.3.1 中规定的扩展时,才有必要应用第二条规则。

14.11.2 Runtime Semantics: 求值

WithStatement : with ( Expression ) Statement
  1. val 为 ? 对 Expression 求值。
  2. obj 为 ? ToObject(? GetValue(val))。
  3. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  4. newEnvNewObjectEnvironment(obj, true, oldEnv)。
  5. 将当前运行执行上下文的 LexicalEnvironment 设为 newEnv
  6. stmtCompletionCompletion(对 Statement 求值)。
  7. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
  8. 返回 ? UpdateEmpty(stmtCompletion, undefined)。
Note

无论控制如何离开所嵌入的 Statement,无论是正常完成、某种突然完成还 是异常,LexicalEnvironment 总是会恢复到其原先状态。

14.12 switch 语句

语法

SwitchStatement[Yield, Await, Return] : switch ( Expression[+In, ?Yield, ?Await] ) CaseBlock[?Yield, ?Await, ?Return] CaseBlock[Yield, Await, Return] : { CaseClauses[?Yield, ?Await, ?Return]opt } { CaseClauses[?Yield, ?Await, ?Return]opt DefaultClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return]opt } CaseClauses[Yield, Await, Return] : CaseClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return] CaseClause[?Yield, ?Await, ?Return] CaseClause[Yield, Await, Return] : case Expression[+In, ?Yield, ?Await] : StatementList[?Yield, ?Await, ?Return]opt DefaultClause[Yield, Await, Return] : default : StatementList[?Yield, ?Await, ?Return]opt

14.12.1 Static Semantics: 早期错误

SwitchStatement : switch ( Expression ) CaseBlock

14.12.2 Runtime Semantics: CaseBlockEvaluation

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

CaseBlock : { }
  1. 返回 undefined
CaseBlock : { CaseClauses }
  1. resultValueundefined
  2. caseClausesCaseClausesCaseClause 项构成的列表, 按源文本顺序排列。
  3. foundfalse
  4. 对于 caseClauses 中的每个 CaseClause clause,执行
    1. 如果 foundfalse,那么
      1. found 设为 ? CaseClauseIsSelected(clause, input)。
    2. 如果 foundtrue,那么
      1. completionCompletion(对 clause 求值)。
      2. 如果 completion.[[Value]] 不为 empty,将 resultValue 设为 completion.[[Value]]
      3. 如果 completion 是一个突然完成,返回 ? UpdateEmpty(completion, resultValue)。
  5. 返回 resultValue
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. resultValueundefined
  2. 如果第一个 CaseClauses 存在,那么
    1. caseClauses 为第一个 CaseClausesCaseClause 项构成 的列表,按源文本顺序排列。
  3. 否则,
    1. caseClauses 为一个新的空列表。
  4. foundfalse
  5. 对于 caseClauses 中的每个 CaseClause clause,执行
    1. 如果 foundfalse,那么
      1. found 设为 ? CaseClauseIsSelected(clause, input)。
    2. 如果 foundtrue,那么
      1. completionCompletion(对 clause 求值)。
      2. 如果 completion.[[Value]] 不为 empty,将 resultValue 设为 completion.[[Value]]
      3. 如果 completion 是一个突然完成,返回 ? UpdateEmpty(completion, resultValue)。
  6. foundInBfalse
  7. 如果第二个 CaseClauses 存在,那么
    1. secondCaseClauses 为第二个 CaseClausesCaseClause 项构成的列表,按源文本顺序排列。
  8. 否则,
    1. secondCaseClauses 为一个新的空列表。
  9. 如果 foundfalse,那么
    1. 对于 secondCaseClauses 中的每个 CaseClause clause,执行
      1. 如果 foundInBfalse,那么
        1. foundInB 设为 ? CaseClauseIsSelected(clause, input)。
      2. 如果 foundInBtrue,那么
        1. completionCompletion(对 CaseClause clause 求值)。
        2. 如果 completion.[[Value]] 不为 empty,将 resultValue 设为 completion.[[Value]]
        3. 如果 completion 是一个突然完成,返回 ? UpdateEmpty(completion, resultValue)。
  10. 如果 foundInBtrue,返回 resultValue
  11. defaultRCompletion(对 DefaultClause 求值)。
  12. 如果 defaultR.[[Value]] 不为 empty,将 resultValue 设为 defaultR.[[Value]]
  13. 如果 defaultR 是一个突然完成,返回 ? UpdateEmpty(defaultR, resultValue)。
  14. NOTE: 以下是对第二个 CaseClauses 的又一次完整迭代。
  15. 对于 secondCaseClauses 中的每个 CaseClause clause,执行
    1. completionCompletion(对 CaseClause clause 求值)。
    2. 如果 completion.[[Value]] 不为 empty,将 resultValue 设为 completion.[[Value]]
    3. 如果 completion 是一个突然完成,返回 ? UpdateEmpty(completion, resultValue)。
  16. 返回 resultValue

14.12.3 Runtime Semantics: CaseClauseIsSelected ( constructor, input )

The abstract operation CaseClauseIsSelected takes arguments constructor (一个 CaseClause Parse Node) and input (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个突然完成. 它判定 constructor 是否匹配 input。 It performs the following steps when called:

  1. 断言:constructor 是产生式 CaseClause : case Expression : StatementListopt 的一个实例。
  2. exprRef 为 ? 对 constructorExpression 求值。
  3. clauseSelector 为 ? GetValue(exprRef)。
  4. 返回 IsStrictlyEqual(input, clauseSelector)。
Note

该操作不会执行 constructorStatementList(如果有)。 CaseBlock 算法使用它的返回值来决定从哪个 StatementList 开始执行。

14.12.4 Runtime Semantics: 求值

SwitchStatement : switch ( Expression ) CaseBlock
  1. exprRef 为 ? 对 Expression 求值。
  2. switchValue 为 ? GetValue(exprRef)。
  3. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  4. blockEnvNewDeclarativeEnvironment(oldEnv)。
  5. 执行 BlockDeclarationInstantiation(CaseBlock, blockEnv)。
  6. 将当前运行执行上下文的 LexicalEnvironment 设为 blockEnv
  7. blockResultCompletion(对 CaseBlock 执行 CaseBlockEvaluation,并以 switchValue 为参数)。
  8. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
  9. 返回 blockResult
Note

无论控制如何离开 SwitchStatement,LexicalEnvironment 总是会恢复到其原先状态。

CaseClause : case Expression :
  1. 返回 empty
CaseClause : case Expression : StatementList
  1. 返回 ? 对 StatementList 求值。
DefaultClause : default :
  1. 返回 empty
DefaultClause : default : StatementList
  1. 返回 ? 对 StatementList 求值。

14.13 带标签语句

语法

LabelledStatement[Yield, Await, Return] : LabelIdentifier[?Yield, ?Await] : LabelledItem[?Yield, ?Await, ?Return] LabelledItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] FunctionDeclaration[?Yield, ?Await, ~Default] Note

Statement 可以带有一个前缀标签。带标签语句仅与带标签的 breakcontinue 语句一起使用。ECMAScript 没有 goto 语句。一个 Statement 可以是某个 LabelledStatement 的一部分,而该 LabelledStatement 本身又 可以是另一个 LabelledStatement 的一部分,以此类推。以这种方式引入的标签 在描述各个语句语义时统称为“当前标签集”。

14.13.1 Static Semantics: 早期错误

LabelledItem : FunctionDeclaration

14.13.2 Static Semantics: IsLabelledFunction ( stmt )

The abstract operation IsLabelledFunction takes argument stmt (一个 Statement Parse Node) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 stmt 不是一个 LabelledStatement,返回 false
  2. itemstmtLabelledItem
  3. 如果 item LabelledItem : FunctionDeclaration ,返回 true
  4. subStmtitemStatement
  5. 返回 IsLabelledFunction(subStmt)。

14.13.3 Runtime Semantics: 求值

LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 ? 对该 LabelledStatement 执行 LabelledEvaluation,并以 « » 为参数。

14.13.4 Runtime Semantics: LabelledEvaluation

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

BreakableStatement : IterationStatement
  1. stmtResultCompletion(对 IterationStatement 执行 LoopEvaluation,并以 labelSet 为参数)。
  2. 如果 stmtResult 是一个 break 完成,那么
    1. 如果 stmtResult.[[Target]]empty,那么
      1. 如果 stmtResult.[[Value]]empty,将 stmtResult 设为 NormalCompletion(undefined)。
      2. 否则,将 stmtResult 设为 NormalCompletion(stmtResult.[[Value]])。
  3. 返回 ? stmtResult
BreakableStatement : SwitchStatement
  1. stmtResultCompletion(对 SwitchStatement 求值)。
  2. 如果 stmtResult 是一个 break 完成,那么
    1. 如果 stmtResult.[[Target]]empty,那么
      1. 如果 stmtResult.[[Value]]empty,将 stmtResult 设为 NormalCompletion(undefined)。
      2. 否则,将 stmtResult 设为 NormalCompletion(stmtResult.[[Value]])。
  3. 返回 ? stmtResult
Note 1

BreakableStatement 是指可以通过一个不带标签的 BreakStatement 退出的语句。

LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. newLabelSetlabelSet 与 « label » 的列表串接。
  3. stmtResultCompletion(对 LabelledItem 执行 LabelledEvaluation,并以 newLabelSet 为参数)。
  4. 如果 stmtResult 是一个 break 完成stmtResult.[[Target]]label,那么
    1. stmtResult 设为 NormalCompletion(stmtResult.[[Value]])。
  5. 返回 ? stmtResult
LabelledItem : FunctionDeclaration
  1. 返回 ? 对 FunctionDeclaration 求值。
Statement : BlockStatement VariableStatement EmptyStatement ExpressionStatement IfStatement ContinueStatement BreakStatement ReturnStatement WithStatement ThrowStatement TryStatement DebuggerStatement
  1. 返回 ? 对 Statement 求值。
Note 2

Statement 中仅有两个产生式在 LabelledEvaluation 上具有特殊语义: BreakableStatementLabelledStatement

14.14 throw 语句

语法

ThrowStatement[Yield, Await] : throw [no LineTerminator here] Expression[+In, ?Yield, ?Await] ;

14.14.1 Runtime Semantics: 求值

ThrowStatement : throw Expression ;
  1. exprRef 为 ? 对 Expression 求值。
  2. exprValue 为 ? GetValue(exprRef)。
  3. 抛出 exprValue

14.15 try 语句

语法

TryStatement[Yield, Await, Return] : try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] Catch[Yield, Await, Return] : catch ( CatchParameter[?Yield, ?Await] ) Block[?Yield, ?Await, ?Return] catch Block[?Yield, ?Await, ?Return] Finally[Yield, Await, Return] : finally Block[?Yield, ?Await, ?Return] CatchParameter[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await] Note

try 语句包围了一段可能发生异常情况的代码块,例如运行时错误或一条 throw 语句。catch 子句提供异常处理代码。当 catch 子句捕获一个异常时, 它的 CatchParameter 会绑定到该异常。

14.15.1 Static Semantics: 早期错误

Catch : catch ( CatchParameter ) Block

14.15.2 Runtime Semantics: CatchClauseEvaluation

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

Catch : catch ( CatchParameter ) Block
  1. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  2. catchEnvNewDeclarativeEnvironment(oldEnv)。
  3. 对于 CatchParameterBoundNames 中的每个元素 argName,执行
    1. 执行 ! catchEnv.CreateMutableBinding(argName, false)。
  4. 将当前运行执行上下文的 LexicalEnvironment 设为 catchEnv
  5. statusCompletion(对 CatchParameter 执行 BindingInitialization,并以 thrownValuecatchEnv 为参数)。
  6. 如果 status 是一个突然完成,那么
    1. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
    2. 返回 ? status
  7. blockCompletionCompletion(对 Block 求值)。
  8. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
  9. 返回 ? blockCompletion
Catch : catch Block
  1. 返回 ? 对 Block 求值。
Note

无论控制如何离开 Block,LexicalEnvironment 总是会恢复到其原先状态。

14.15.3 Runtime Semantics: 求值

TryStatement : try Block Catch
  1. blockResultCompletion(对 Block 求值)。
  2. 如果 blockResult 是一个 throw 完成,令 catchResultCompletion(对 Catch 执行 CatchClauseEvaluation,并以 blockResult.[[Value]] 为参数)。
  3. 否则,令 catchResultblockResult
  4. 返回 ? UpdateEmpty(catchResult, undefined)。
TryStatement : try Block Finally
  1. blockResultCompletion(对 Block 求值)。
  2. finallyResultCompletion(对 Finally 求值)。
  3. 如果 finallyResult 是一个正常完成,将 finallyResult 设为 blockResult
  4. 返回 ? UpdateEmpty(finallyResult, undefined)。
TryStatement : try Block Catch Finally
  1. blockResultCompletion(对 Block 求值)。
  2. 如果 blockResult 是一个 throw 完成,令 catchResultCompletion(对 Catch 执行 CatchClauseEvaluation,并以 blockResult.[[Value]] 为参数)。
  3. 否则,令 catchResultblockResult
  4. finallyResultCompletion(对 Finally 求值)。
  5. 如果 finallyResult 是一个正常完成,将 finallyResult 设为 catchResult
  6. 返回 ? UpdateEmpty(finallyResult, undefined)。

14.16 debugger 语句

语法

DebuggerStatement : debugger ;

14.16.1 Runtime Semantics: 求值

Note

DebuggerStatement 求值时,实现可以在调试器环境下触发断点。如 果调试器不存在或未启用,该语句没有可观察效果。

DebuggerStatement : debugger ;
  1. 如果存在并启用了某种实现定义的调试设施,那么
    1. 执行一个实现定义的调试动作。
    2. 返回一个新的实现定义Completion Record
  2. 返回 empty