14.7 Iteration Statements
Syntax
14.7.1 Semantics
14.7.1.1 LoopContinues ( completion, labelSet )
The abstract operation LoopContinues takes arguments completion (a
- If completion is a
normal completion , returntrue . - If completion is not a
continue completion , returnfalse . - If completion.[[Target]] is
empty , returntrue . - If labelSet contains completion.[[Target]], return
true . - Return
false .
Within the
14.7.1.2 Runtime Semantics: LoopEvaluation
The
- Return ?
DoWhileLoopEvaluation ofDoWhileStatement with argument labelSet.
- Return ?
WhileLoopEvaluation ofWhileStatement with argument labelSet.
- Return ?
ForLoopEvaluation ofForStatement with argument labelSet.
- Return ?
ForInOfLoopEvaluation ofForInOfStatement with argument labelSet.
14.7.2 The do
-while
Statement
Syntax
14.7.2.1 Static Semantics: Early Errors
-
It is a Syntax Error if
IsLabelledFunction (Statement ) istrue .
It is only necessary to apply this rule if the extension specified in
14.7.2.2 Runtime Semantics: DoWhileLoopEvaluation
The
- Let V be
undefined . - Repeat,
- Let stmtResult be
Completion (Evaluation ofStatement ). - If
LoopContinues (stmtResult, labelSet) isfalse , return ?UpdateEmpty (stmtResult, V). - If stmtResult.[[Value]] is not
empty , set V to stmtResult.[[Value]]. - Let exprRef be ?
Evaluation ofExpression . - Let exprValue be ?
GetValue (exprRef). - If
ToBoolean (exprValue) isfalse , return V.
- Let stmtResult be
14.7.3 The while
Statement
Syntax
14.7.3.1 Static Semantics: Early Errors
-
It is a Syntax Error if
IsLabelledFunction (Statement ) istrue .
It is only necessary to apply this rule if the extension specified in
14.7.3.2 Runtime Semantics: WhileLoopEvaluation
The
- Let V be
undefined . - Repeat,
- Let exprRef be ?
Evaluation ofExpression . - Let exprValue be ?
GetValue (exprRef). - If
ToBoolean (exprValue) isfalse , return V. - Let stmtResult be
Completion (Evaluation ofStatement ). - If
LoopContinues (stmtResult, labelSet) isfalse , return ?UpdateEmpty (stmtResult, V). - If stmtResult.[[Value]] is not
empty , set V to stmtResult.[[Value]].
- Let exprRef be ?
14.7.4 The for
Statement
Syntax
14.7.4.1 Static Semantics: Early Errors
-
It is a Syntax Error if
IsLabelledFunction (Statement ) istrue .
It is only necessary to apply this rule if the extension specified in
-
It is a Syntax Error if any element of the
BoundNames ofLexicalDeclaration also occurs in theVarDeclaredNames ofStatement .
14.7.4.2 Runtime Semantics: ForLoopEvaluation
The
- If the first
Expression is present, then- Let exprRef be ?
Evaluation of the firstExpression . - Perform ?
GetValue (exprRef).
- Let exprRef be ?
- If the second
Expression is present, let test be the secondExpression ; otherwise, let test beempty . - If the third
Expression is present, let increment be the thirdExpression ; otherwise, let increment beempty . - Return ?
ForBodyEvaluation (test, increment,Statement , « », labelSet).
- Perform ?
Evaluation ofVariableDeclarationList . - If the first
Expression is present, let test be the firstExpression ; otherwise, let test beempty . - If the second
Expression is present, let increment be the secondExpression ; otherwise, let increment beempty . - Return ?
ForBodyEvaluation (test, increment,Statement , « », labelSet).
- Let oldEnv be the
running execution context 's LexicalEnvironment. - Let loopEnv be
NewDeclarativeEnvironment (oldEnv). - Let isConst be
IsConstantDeclaration ofLexicalDeclaration . - Let boundNames be the
BoundNames ofLexicalDeclaration . - For each element dn of boundNames, do
- If isConst is
true , then- Perform ! loopEnv.CreateImmutableBinding(dn,
true ).
- Perform ! loopEnv.CreateImmutableBinding(dn,
- Else,
- Perform ! loopEnv.CreateMutableBinding(dn,
false ).
- Perform ! loopEnv.CreateMutableBinding(dn,
- If isConst is
- Set the
running execution context 's LexicalEnvironment to loopEnv. - Let forDcl be
Completion (Evaluation ofLexicalDeclaration ). - If forDcl is an
abrupt completion , then- Set the
running execution context 's LexicalEnvironment to oldEnv. - Return ? forDcl.
- Set the
- If isConst is
false , let perIterationLets be boundNames; otherwise let perIterationLets be a new emptyList . - If the first
Expression is present, let test be the firstExpression ; otherwise, let test beempty . - If the second
Expression is present, let increment be the secondExpression ; otherwise, let increment beempty . - Let bodyResult be
Completion (ForBodyEvaluation (test, increment,Statement , perIterationLets, labelSet)). - Set the
running execution context 's LexicalEnvironment to oldEnv. - Return ? bodyResult.
14.7.4.3 ForBodyEvaluation ( test, increment, stmt, perIterationBindings, labelSet )
The abstract operation ForBodyEvaluation takes arguments test (an
- Let V be
undefined . - Perform ?
CreatePerIterationEnvironment (perIterationBindings). - Repeat,
- If test is not
empty , then- Let testRef be ?
Evaluation of test. - Let testValue be ?
GetValue (testRef). - If
ToBoolean (testValue) isfalse , return V.
- Let testRef be ?
- Let result be
Completion (Evaluation of stmt). - If
LoopContinues (result, labelSet) isfalse , return ?UpdateEmpty (result, V). - If result.[[Value]] is not
empty , set V to result.[[Value]]. - Perform ?
CreatePerIterationEnvironment (perIterationBindings). - If increment is not
empty , then- Let incRef be ?
Evaluation of increment. - Perform ?
GetValue (incRef).
- Let incRef be ?
- If test is not
14.7.4.4 CreatePerIterationEnvironment ( perIterationBindings )
The abstract operation CreatePerIterationEnvironment takes argument perIterationBindings (a
- If perIterationBindings has any elements, then
- Let lastIterationEnv be the
running execution context 's LexicalEnvironment. - Let outer be lastIterationEnv.[[OuterEnv]].
Assert : outer is notnull .- Let thisIterationEnv be
NewDeclarativeEnvironment (outer). - For each element bn of perIterationBindings, do
- Perform ! thisIterationEnv.CreateMutableBinding(bn,
false ). - Let lastValue be ? lastIterationEnv.GetBindingValue(bn,
true ). - Perform ! thisIterationEnv.InitializeBinding(bn, lastValue).
- Perform ! thisIterationEnv.CreateMutableBinding(bn,
- Set the
running execution context 's LexicalEnvironment to thisIterationEnv.
- Let lastIterationEnv be the
- Return
unused .
14.7.5 The for
-in
, for
-of
, and for
-await
-of
Statements
Syntax
This section is extended by Annex
14.7.5.1 Static Semantics: Early Errors
-
It is a Syntax Error if
IsLabelledFunction (Statement ) istrue .
It is only necessary to apply this rule if the extension specified in
If
If
-
It is a Syntax Error if
AssignmentTargetType ofLeftHandSideExpression is notsimple .
-
It is a Syntax Error if the
BoundNames ofForDeclaration contains"let" . -
It is a Syntax Error if any element of the
BoundNames ofForDeclaration also occurs in theVarDeclaredNames ofStatement . -
It is a Syntax Error if the
BoundNames ofForDeclaration contains any duplicate entries.
14.7.5.2 Static Semantics: IsDestructuring
The
- If
PrimaryExpression is either anObjectLiteral or anArrayLiteral , returntrue . - Return
false .
- Return
false .
- Return
IsDestructuring ofForBinding .
- Return
false .
- Return
true .
This section is extended by Annex
14.7.5.3 Runtime Semantics: ForDeclarationBindingInitialization
The
var
statements and the formal parameter lists of some
It is defined piecewise over the following productions:
- Return ?
BindingInitialization ofForBinding with arguments value and environment.
14.7.5.4 Runtime Semantics: ForDeclarationBindingInstantiation
The
- For each element name of the
BoundNames ofForBinding , do- If
IsConstantDeclaration ofLetOrConst istrue , then- Perform ! environment.CreateImmutableBinding(name,
true ).
- Perform ! environment.CreateImmutableBinding(name,
- Else,
- Perform ! environment.CreateMutableBinding(name,
false ).
- Perform ! environment.CreateMutableBinding(name,
- If
- Return
unused .
14.7.5.5 Runtime Semantics: ForInOfLoopEvaluation
The
- Let keyResult be ?
ForIn/OfHeadEvaluation (« »,Expression ,enumerate ). - Return ?
ForIn/OfBodyEvaluation (LeftHandSideExpression ,Statement , keyResult,enumerate ,assignment , labelSet).
- Let keyResult be ?
ForIn/OfHeadEvaluation (« »,Expression ,enumerate ). - Return ?
ForIn/OfBodyEvaluation (ForBinding ,Statement , keyResult,enumerate ,var-binding , labelSet).
- Let keyResult be ?
ForIn/OfHeadEvaluation (BoundNames ofForDeclaration ,Expression ,enumerate ). - Return ?
ForIn/OfBodyEvaluation (ForDeclaration ,Statement , keyResult,enumerate ,lexical-binding , labelSet).
- Let keyResult be ?
ForIn/OfHeadEvaluation (« »,AssignmentExpression ,iterate ). - Return ?
ForIn/OfBodyEvaluation (LeftHandSideExpression ,Statement , keyResult,iterate ,assignment , labelSet).
- Let keyResult be ?
ForIn/OfHeadEvaluation (« »,AssignmentExpression ,iterate ). - Return ?
ForIn/OfBodyEvaluation (ForBinding ,Statement , keyResult,iterate ,var-binding , labelSet).
- Let keyResult be ?
ForIn/OfHeadEvaluation (BoundNames ofForDeclaration ,AssignmentExpression ,iterate ). - Return ?
ForIn/OfBodyEvaluation (ForDeclaration ,Statement , keyResult,iterate ,lexical-binding , labelSet).
- Let keyResult be ?
ForIn/OfHeadEvaluation (« »,AssignmentExpression ,async-iterate ). - Return ?
ForIn/OfBodyEvaluation (LeftHandSideExpression ,Statement , keyResult,iterate ,assignment , labelSet,async ).
- Let keyResult be ?
ForIn/OfHeadEvaluation (« »,AssignmentExpression ,async-iterate ). - Return ?
ForIn/OfBodyEvaluation (ForBinding ,Statement , keyResult,iterate ,var-binding , labelSet,async ).
- Let keyResult be ?
ForIn/OfHeadEvaluation (BoundNames ofForDeclaration ,AssignmentExpression ,async-iterate ). - Return ?
ForIn/OfBodyEvaluation (ForDeclaration ,Statement , keyResult,iterate ,lexical-binding , labelSet,async ).
This section is extended by Annex
14.7.5.6 ForIn/OfHeadEvaluation ( uninitializedBoundNames, expr, iterationKind )
The abstract operation ForIn/OfHeadEvaluation takes arguments uninitializedBoundNames (a
- Let oldEnv be the
running execution context 's LexicalEnvironment. - If uninitializedBoundNames is not empty, then
Assert : uninitializedBoundNames has no duplicate entries.- Let newEnv be
NewDeclarativeEnvironment (oldEnv). - For each String name of uninitializedBoundNames, do
- Perform ! newEnv.CreateMutableBinding(name,
false ).
- Perform ! newEnv.CreateMutableBinding(name,
- Set the
running execution context 's LexicalEnvironment to newEnv.
- Let exprRef be
Completion (Evaluation of expr). - Set the
running execution context 's LexicalEnvironment to oldEnv. - Let exprValue be ?
GetValue (? exprRef). - If iterationKind is
enumerate , then- If exprValue is either
undefined ornull , then- Return
Completion Record { [[Type]]:break , [[Value]]:empty , [[Target]]:empty }.
- Return
- Let obj be !
ToObject (exprValue). - Let iterator be
EnumerateObjectProperties (obj). - Let nextMethod be !
GetV (iterator,"next" ). - Return the
Iterator Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]:false }.
- If exprValue is either
- Else,
Assert : iterationKind is eitheriterate orasync-iterate .- If iterationKind is
async-iterate , let iteratorKind beasync . - Else, let iteratorKind be
sync . - Return ?
GetIterator (exprValue, iteratorKind).
14.7.5.7 ForIn/OfBodyEvaluation ( lhs, stmt, iteratorRecord, iterationKind, lhsKind, labelSet [ , iteratorKind ] )
The abstract operation ForIn/OfBodyEvaluation takes arguments lhs (a
- If iteratorKind is not present, set iteratorKind to
sync . - Let oldEnv be the
running execution context 's LexicalEnvironment. - Let V be
undefined . - Let destructuring be
IsDestructuring of lhs. - If destructuring is
true and lhsKind isassignment , thenAssert : lhs is aLeftHandSideExpression .- Let assignmentPattern be the
AssignmentPattern that iscovered by lhs.
- Repeat,
- Let nextResult be ?
Call (iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]). - If iteratorKind is
async , set nextResult to ?Await (nextResult). - If nextResult
is not an Object , throw aTypeError exception. - Let done be ?
IteratorComplete (nextResult). - If done is
true , return V. - Let nextValue be ?
IteratorValue (nextResult). - If lhsKind is either
assignment orvar-binding , then- If destructuring is
true , then- If lhsKind is
assignment , then- Let status be
Completion (DestructuringAssignmentEvaluation of assignmentPattern with argument nextValue).
- Let status be
- Else,
Assert : lhsKind isvar-binding .Assert : lhs is aForBinding .- Let status be
Completion (BindingInitialization of lhs with arguments nextValue andundefined ).
- If lhsKind is
- Else,
- Let lhsRef be
Completion (Evaluation of lhs). (It may be evaluated repeatedly.) - If lhsRef is an
abrupt completion , then- Let status be lhsRef.
- Else,
- Let status be
Completion (PutValue (lhsRef.[[Value]], nextValue)).
- Let status be
- Let lhsRef be
- If destructuring is
- Else,
Assert : lhsKind islexical-binding .Assert : lhs is aForDeclaration .- Let iterationEnv be
NewDeclarativeEnvironment (oldEnv). - Perform
ForDeclarationBindingInstantiation of lhs with argument iterationEnv. - Set the
running execution context 's LexicalEnvironment to iterationEnv. - If destructuring is
true , then- Let status be
Completion (ForDeclarationBindingInitialization of lhs with arguments nextValue and iterationEnv).
- Let status be
- Else,
Assert : lhs binds a single name.- Let lhsName be the sole element of
BoundNames of lhs. - Let lhsRef be !
ResolveBinding (lhsName). - Let status be
Completion (InitializeReferencedBinding (lhsRef, nextValue)).
- If status is an
abrupt completion , then- Set the
running execution context 's LexicalEnvironment to oldEnv. - If iteratorKind is
async , return ?AsyncIteratorClose (iteratorRecord, status). - If iterationKind is
enumerate , then- Return ? status.
- Else,
Assert : iterationKind isiterate .- Return ?
IteratorClose (iteratorRecord, status).
- Set the
- Let result be
Completion (Evaluation of stmt). - Set the
running execution context 's LexicalEnvironment to oldEnv. - If
LoopContinues (result, labelSet) isfalse , then- If iterationKind is
enumerate , then- Return ?
UpdateEmpty (result, V).
- Return ?
- Else,
Assert : iterationKind isiterate .- Set status to
Completion (UpdateEmpty (result, V)). - If iteratorKind is
async , return ?AsyncIteratorClose (iteratorRecord, status). - Return ?
IteratorClose (iteratorRecord, status).
- If iterationKind is
- If result.[[Value]] is not
empty , set V to result.[[Value]].
- Let nextResult be ?
14.7.5.8 Runtime Semantics: Evaluation
- Let bindingId be
StringValue ofBindingIdentifier . - Return ?
ResolveBinding (bindingId).
14.7.5.9 EnumerateObjectProperties ( O )
The abstract operation EnumerateObjectProperties takes argument O (an Object) and returns an Iterator. It performs the following steps when called:
- Return an Iterator object (
27.1.1.2 ) whosenext
method iterates over all the String-valued keys of enumerable properties of O. The iterator object is never directly accessible to ECMAScript code. The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below.
The iterator's throw
and return
methods are next
method processes object properties to determine whether the next
method is ignored. If new properties are added to the target object during enumeration, the newly added properties are not guaranteed to be processed in the active enumeration. A next
method at most once in any enumeration.
Enumerating the properties of the target object includes enumerating properties of its prototype, and the prototype of the prototype, and so on, recursively; but a property of a prototype is not processed if it has the same name as a property that has already been processed by the iterator's next
method. The values of [[Enumerable]] attributes are not considered when determining if a property of a prototype object has already been processed. The enumerable property names of prototype objects must be obtained by invoking EnumerateObjectProperties passing the prototype object as the argument. EnumerateObjectProperties must obtain the own
In addition, if neither O nor any object in its prototype chain is a
- the value of the [[Prototype]] internal slot of O or an object in its prototype chain changes,
- a property is removed from O or an object in its prototype chain,
- a property is added to an object in O's prototype chain, or
- the value of the [[Enumerable]] attribute of a property of O or an object in its prototype chain changes.
ECMAScript implementations are not required to implement the algorithm in
The following is an informative definition of an ECMAScript generator function that conforms to these rules:
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;
}
}
14.7.5.10 For-In Iterator Objects
A For-In Iterator is an object that represents a specific iteration over some specific object. For-In Iterator objects are never directly accessible to ECMAScript code; they exist solely to illustrate the behaviour of
14.7.5.10.1 CreateForInIterator ( object )
The abstract operation CreateForInIterator takes argument object (an Object) and returns a For-In Iterator. It is used to create a For-In Iterator object which iterates over the own and inherited enumerable string properties of object in a specific order. It performs the following steps when called:
- Let iterator be
OrdinaryObjectCreate (%ForInIteratorPrototype% , « [[Object]], [[ObjectWasVisited]], [[VisitedKeys]], [[RemainingKeys]] »). - Set iterator.[[Object]] to object.
- Set iterator.[[ObjectWasVisited]] to
false . - Set iterator.[[VisitedKeys]] to a new empty
List . - Set iterator.[[RemainingKeys]] to a new empty
List . - Return iterator.
14.7.5.10.2 The %ForInIteratorPrototype% Object
The %ForInIteratorPrototype% object:
- has properties that are inherited by all For-In Iterator Objects.
- is an
ordinary object . - has a [[Prototype]] internal slot whose value is
%IteratorPrototype% . - is never directly accessible to ECMAScript code.
- has the following properties:
14.7.5.10.2.1 %ForInIteratorPrototype%.next ( )
- Let O be the
this value. Assert : Ois an Object .Assert : O has all of the internal slots of a For-In Iterator Instance (14.7.5.10.3 ).- Let object be O.[[Object]].
- Repeat,
- If O.[[ObjectWasVisited]] is
false , then- Let keys be ? object.[[OwnPropertyKeys]]().
- For each element key of keys, do
- If key
is a String , then- Append key to O.[[RemainingKeys]].
- If key
- Set O.[[ObjectWasVisited]] to
true .
- Repeat, while O.[[RemainingKeys]] is not empty,
- Let r be the first element of O.[[RemainingKeys]].
- Remove the first element from O.[[RemainingKeys]].
- If there does not exist an element v of O.[[VisitedKeys]] such that
SameValue (r, v) istrue , then- Let desc be ? object.[[GetOwnProperty]](r).
- If desc is not
undefined , then- Append r to O.[[VisitedKeys]].
- If desc.[[Enumerable]] is
true , returnCreateIterResultObject (r,false ).
- Set object to ? object.[[GetPrototypeOf]]().
- Set O.[[Object]] to object.
- Set O.[[ObjectWasVisited]] to
false . - If object is
null , returnCreateIterResultObject (undefined ,true ).
- If O.[[ObjectWasVisited]] is
14.7.5.10.3 Properties of For-In Iterator Instances
For-In Iterator instances are
Internal Slot | Type | Description |
---|---|---|
[[Object]] | an Object | The Object value whose properties are being iterated. |
[[ObjectWasVisited]] | a Boolean |
|
[[VisitedKeys]] |
a |
The values that have been emitted by this iterator thus far. |
[[RemainingKeys]] |
a |
The values remaining to be emitted for the current object, before iterating the properties of its prototype (if its prototype is not |