ECMAScript | Операторы итерации

Синтаксис операторов итерации

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 )

Абстрактная операция LoopContinues принимает аргументы completion и labelSet. На русском эта функция выглядит примерно так «Цикл продолжается (завершение, набор меток)«.

При вызове она выполняет следующие шаги:

1. Если completion.[[Type]] является normal, вернуть true.
2. Если completion.[[Type]] не является continue, вернуть false.
3. Если completion.[[Target]] является empty, вернуть true.
4. Если completion.[[Target]] является элементом из labelSet, вернуть true.
5. Вернуть false.
Примечание

В части Statement из IterationStatement можно использовать ContinueStatement для начала новой итерации.

 

Семантика времени выполнения: оценка цикла

С параметром labelSet.

IterationStatement : DoWhileStatement

Вернуть ? DoWhileLoopEvaluation из DoWhileStatement с аргументом labelSet.

IterationStatement : WhileStatement

 ? WhileLoopEvaluation из WhileStatement с аргументом labelSet.

IterationStatement : ForStatement

 ? ForLoopEvaluation из ForStatement с аргументом labelSet.

IterationStatement : ForInOfStatement

 ? ForInOfLoopEvaluation из ForInOfStatement с аргументом labelSet.

 

14.7.2 Оператор do-while

Синтаксис оператора do-while

DoWhileStatement [Yield, Await, Return] :

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

 

14.7.2.1 Статическая семантика: Ранние Ошибки

DoWhileStatement : do Statement while ( Expression ) ;

Если IsLabelledFunction(Statement) истинно true, это синтаксическая ошибка.

Примечание

Это правило необходимо применять только в том случае, если реализовано расширение, указанное в B.3.2.

 

14.7.2.2 Семантика времени выполнения: DoWhileLoopEvaluation

С параметром labelSet.

DoWhileStatement : do Statement while ( Expression ) ;

1. Пусть V будет undefined.
Повторять,
 stmtResult будет результатом оценки Statement.
Если LoopContinues(stmtResultlabelSet) является false, вернуть Completion(UpdateEmpty(stmtResultV)).
Если stmtResult.[[Value]] не является empty, установить V на stmtResult.[[Value]].
 exprRef будет результатом оценки Expression.
 exprValue будет ? GetValue(exprRef).
 ! ToBoolean(exprValue) является false, вернуть NormalCompletion(V).

 

14.7.3 Оператор while

Синтаксис оператора while

WhileStatement [Yield, Await, Return] :

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

14.7.3.1 Статическая семантика: Ранние Ошибки

WhileStatement : while ( Expression ) Statement

Примечание

Это правило необходимо применять только в том случае, если реализовано расширение, указанное в разделе B.3.1.

 

14.7.3.2 Семантика времени выполнения: WhileLoopEvaluation

С параметром labelSet.

WhileStatement : while ( Expression ) Statement

1. Пусть V будет undefined.
2. Повторять,
   a. Пусть exprRef будет результатом вычисления Expression.
   b. Пусть exprValue будет ? GetValue(exprRef).
   c. Если ! ToBoolean(exprValue) является false, вернуть NormalCompletion(V).
   d. Пусть stmtResult будет результатом вычисления Statement.
   e. Если LoopContinues(stmtResult, labelSet) является false, вернуть Completion(UpdateEmpty(stmtResult, V)).
   f. Если stmtResult.[[Value]] не является empty, установить V на 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 Статическая семантика: Ранние Ошибки

ForStatement :

for ( Expression opt ; Expression opt ; Expression opt ) Statement

for ( var VariableDeclarationList ; Expression opt ; Expression opt ) Statement

for ( LexicalDeclaration Expression opt ; Expression opt ) Statement

 

Примечание

Это правило необходимо применять только в том случае, если реализовано расширение, указанное в разделе B.3.1.

 

ForStatement : for ( LexicalDeclaration Expression opt ; Expression opt ) Statement

14.7.4.2 Семантика времени выполнения: ForLoopEvaluation

С параметром labelSet.

ForStatement : for ( Expression opt ; Expression opt ; Expression opt ) Statement

1. Если первое выражение Expression присутствует, то
   a. Пусть exprRef будет результатом вычисления первого выражения Expression.
   b. Выполнить ? GetValue(exprRef).
2. Вернуть ? ForBodyEvaluation(второе выражение Expression, третье выражение Expression, определение Statement, «», labelSet).

ForStatement : for ( var VariableDeclarationList ; Expression opt ; Expression opt ) Statement

1. Пусть varDcl будет результатом вычисления VariableDeclarationList.
2. ReturnIfAbrupt(varDcl).
3. Вернуть ? ForBodyEvaluation(первое выражение Expression, второе выражение Expression, определение Statement, «», labelSet).

ForStatement : for ( LexicalDeclaration Expression opt ; Expression opt ) Statement

1. Пусть oldEnv будет LexicalEnvironment(Лексическая среда) текущего контекста выполнения.
2. Пусть loopEnv будет NewDeclarativeEnvironment(oldEnv).
3. Пусть isConst будет IsConstantDeclaration из LexicalDeclaration.
4. Пусть boundNames будет BoundNames из LexicalDeclaration.
5. Для каждого элемента dn из boundNames выполните
   a. Если isConst является true, тогда
      i. Выполнить ! loopEnv.CreateImmutableBinding(dn, true).
   b. Иначе,
      i. Выполнить ! loopEnv.CreateMutableBinding(dn, false).
6. Установите для LexicalEnvironment(Лексическая среда) текущего контекста выполнения значение loopEnv.
7. Пусть forDcl будет результатом вычисления LexicalDeclaration.
8. Если forDcl является внезапным завершением, тогда
   a. Установите для LexicalEnvironment текущего контекста выполнения значение oldEnv.
   b. Вернуть Completion(forDcl).
9. Если isConst имеет значение false, пусть perIterationLets будет boundNames; в противном случае пусть perIterationLets будет «».
10. Пусть bodyResult будет ForBodyEvaluation(первое выражение Expression, второе выражение Expression, определение Statement, perIterationLets, labelSet).
11. Установите для LexicalEnvironment текущего контекста выполнения значение oldEnv.
12. Вернуть Завершение Completion(bodyResult).

 

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

Абстрактная операция ForBodyEvaluation принимает аргументы test, increment, stmt, perIterationBindings и labelSet. При вызове она выполняет следующие шаги:

1. Пусть V будет undefined.
2. Выполнить ? CreatePerIterationEnvironment(perIterationBindings).
3. Повторять,
   a. Если тест не [empty], то
      i. Пусть testRef будет результатом оценки test.
      ii. Пусть testValue будет ? GetValue(testRef).
      iii. Если ! ToBoolean(testValue) является false, вернуть NormalCompletion(V).
   b. Пусть result будет результатом вычисления stmt.
   c. Если LoopContinues(result, labelSet) имеет значение false, вернуть Completion(UpdateEmpty(result, V)).
   d. Если result.[[Value]] не empty, установите V равным result.[[Value]].
   e. Выполнить ? CreatePerIterationEnvironment(perIterationBindings).
   f. Если инкремент increment не [empty], то
      i. Пусть incRef будет результатом вычисления приращения increment.
      ii. Выполнить ? GetValue(incRef).

 

14.7.4.4 CreatePerIterationEnvironment ( perIterationBindings )

Абстрактная операция CreatePerIterationEnvironment принимает аргумент perIterationBindings. При вызове она выполняет следующие шаги:

1. Если в perIterationBindings есть какие-либо элементы, то
   a. Пусть lastIterationEnv будет LexicalEnvironment текущего контекста выполнения.
   b. Пусть outer будет lastIterationEnv.[[OuterEnv]].
   c. Утверждено: outer не равен null.
   d. Пусть thisIterationEnv будет NewDeclarativeEnvironment(outer).
   e. Для каждого элемента bn из perIterationBindings выполните
      i. Выполнить ! thisIterationEnv.CreateMutableBinding(bn, false).
      ii. Пусть lastValue будет ? lastIterationEnv.GetBindingValue(bn, true).
      iii. Выполнить thisIterationEnv.InitializeBinding(bn, lastValue).
   f. Установите для LexicalEnvironment текущего контекста выполнения значение thisIterationEnv.
2. Вернуть undefined.

 

 

14.7.5 Оператор for-in, for-of, for-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]

 

Примечание

Этот раздел расширен Приложением B.3.5.

 

14.7.5.1 Статическая семантика: Ранние Ошибки

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

Примечание

Это правило необходимо применять только в том случае, если реализовано расширение, указанное в разделе B.3.1.

 

ForInOfStatement :

for ( LeftHandSideExpression in Expression ) Statement

for ( LeftHandSideExpression of AssignmentExpression ) Statement

for await ( LeftHandSideExpression of AssignmentExpression ) Statement

Если LeftHandSideExpression является ObjectLiteral или ArrayLiteral, применяются следующие правила Ранней Ошибки:

Если LeftHandSideExpression не является ни ObjectLiteral, ни ArrayLiteral, применяется следующее правило Ранней Ошибки:

ForInOfStatement :

for ( ForDeclaration in Expression ) Statement

for ( ForDeclaration of AssignmentExpression ) Statement

for await ( ForDeclaration of AssignmentExpression ) Statement

 

14.7.5.2 Статическая семантика: IsDestructuring

MemberExpression : PrimaryExpression

1. Если PrimaryExpression является ObjectLiteral или ArrayLiteral, верните true.
2. Вернуть false.

MemberExpression :

MemberExpression [ Expression ]

MemberExpression . IdentifierName

MemberExpression TemplateLiteral

SuperProperty

MetaProperty

new MemberExpression Arguments

NewExpression :

new NewExpression

LeftHandSideExpression :

CallExpression

OptionalExpression

1. Вернуть false.

ForDeclaration : LetOrConst ForBinding

1. Вернуть IsDestructuring из ForBinding.

ForBinding : BindingIdentifier

1. Вернуть false.

ForBinding : BindingPattern

1. Вернуть true.
Примечание

Этот раздел расширен Приложением B.3.5

 

14.7.5.3 Семантика времени выполнения: ForDeclarationBindingInitialization

С параметрами value и environment.

Примечание

undefined передается для среды environment, чтобы указать, что для присвоения значения инициализации следует использовать операцию PutValue. Так обстоит дело с операторами var и списками формальных параметров некоторых нестрогих функций (смотри раздел 10.2.11). В этих случаях лексическая привязка поднимается и пре-инициализируется до оценки ее инициализатора.

ForDeclaration : LetOrConst ForBinding

1. Верните результат выполнения BindingInitialization для ForBinding, передав значение value и среду environment в качестве аргументов.

 

14.7.5.4 Семантика времени выполнения: ForDeclarationBindingInstantiation

С параметром environment.

ForDeclaration : LetOrConst ForBinding

1. Утверждено: среда environment - это декларативная запись среды.
2. Для каждого элемента name из связанных имён BoundNames из ForBinding выполните
   a. Если IsConstantDeclaration из LetOrConst истинно true, то
      i. Выполнить ! environment.CreateImmutableBinding(name, true).
   b. Иначе,
      i. Выполнить ! environment.CreateMutableBinding(name, false).

 

14.7.5.5 Семантика времени выполнения: ForInOfLoopEvaluation

С параметром labelSet.

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement

1. Пусть keyResult будет ? ForIn/OfHeadEvaluation(« », Expression, enumerate).
2. Вернуть ? ForIn/OfBodyEvaluation (LeftHandSideExpression, Statement, keyResultenumerateassignmentlabelSet).

ForInOfStatement : for ( var ForBinding in Expression ) Statement

1. Пусть keyResult будет ? ForIn/OfHeadEvaluation(« », Expression, enumerate).
2. Вернуть ? ForIn/OfBodyEvaluation(ForBindingStatementkeyResultenumeratevarBindinglabelSet).

ForInOfStatement : for ( ForDeclaration in Expression ) Statement

1. Пусть keyResult будет ? ForIn/OfHeadEvaluation(BoundNames из ForDeclaration, Expression, enumerate).
2. Вернуть ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, enumerate, lexicalBinding, 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, varBinding, labelSet).

ForInOfStatement : for ( ForDeclaration of AssignmentExpression ) Statement

1. Пусть keyResult будет ? ForIn/OfHeadEvaluation(BoundNames из ForDeclaration, AssignmentExpression, iterate).
2. Вернуть ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexicalBinding, 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, varBinding, labelSet, async).

ForInOfStatement : for await ( ForDeclaration of AssignmentExpression ) Statement

1. Пусть keyResult будет ? ForIn/OfHeadEvaluation(BoundNames из ForDeclaration, AssignmentExpression, async-iterate).
2. Вернуть ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexicalBinding, labelSet, async).
Примечание

Этот раздел расширен Приложением B.3.5.

 

14.7.5.6 ForIn/OfHeadEvaluation ( uninitializedBoundNames, expr, iterationKind )

Абстрактная операция ForIn/OfHeadEvaluation принимает аргументы uninitializedBoundNames, expr и iterationKind (такой как enumerate, iterate или async-iterate). При вызове она выполняет следующие шаги:

1. Пусть oldEnv будет LexicalEnvironment текущего контекста выполнения.
2. Если uninitializedBoundNames не является пустым Списком, тогда
   а. Утверждено: uninitializedBoundNames не имеет повторяющихся записей.
   b. Пусть newEnv будет NewDeclarativeEnvironment(oldEnv).
   c. Для каждого строкового имени name из uninitializedBoundNames выполните
      i. Выполнять ! newEnv.CreateMutableBinding(name, false).
   d. Установите для LexicalEnvironment текущего контекста выполнения значение newEnv.
3. Пусть exprRef будет результатом вычисления expr.
4. Установите LexicalEnvironment текущего контекста выполнения на oldEnv.
5. Пусть exprValue будет ? GetValue(exprRef).
6. Если iterationKind является enumerate, тогда
   а. Если exprValue является undefined(не определено) или равно null, тогда
      i. Вернуть Завершение Completion { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }.
   b. Пусть obj будет ! ToObject(exprValue).
   c. Пусть iterator будет ? EnumerateObjectProperties (obj).
   d. Пусть nextMethod будет ! GetV(iterator, "next").
   е. Вернуть запись Record {[[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false}.
7. Иначе,
   а. Утверждено: iterationKind является iterate или async-iterate.
   b. Если iterationKind является async-iterate, пусть iteratorHint будет async.
   c. В противном случае пусть iteratorHint будет sync.
   d. Вернуть ? GetIterator (exprValue, iteratorHint).

 

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

Абстрактная операция ForIn/OfBodyEvaluation принимает аргументы lhs, stmt, iteratorRecord, iterationKind, lhsKind (такой как assignment, varBinding или lexicalBinding), а также labelSet и необязательный аргумент iteratorKind (такой как sync или async). При вызове она выполняет следующие шаги:

1. Если iteratorKind отсутствует, установите для iteratorKind значение sync.
2. Пусть oldEnv будет LexicalEnvironment текущего контекста выполнения.
3. Пусть V является undefined(не определено).
4. Пусть деструктуризация destructuring будет IsDestructuring из lhs.
5. Если destructuring является true (истинно) и если lhsKind является assignment, то
  а. Утверждено: lhs - это выражение LeftHandSideExpression.
  b. Пусть assignmentPattern будет AssignmentPattern, который покрывается lhs.
6. Повторите,
  а. Пусть nextResult будет ? Вызов (iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).
  b. Если iteratorKind является async, установите для nextResult значение ? Ожидайте Await(nextResult).
  c. Если Тип Type(nextResult) не является Object, вызовите исключение TypeError.
  d. Пусть done будет ? IteratorComplete(nextResult).
  e. Если done является true (истинно), вернуть NormalCompletion(V).
  f. Пусть nextValue будет ? IteratorValue(nextResult).
  g. Если lhsKind является либо assignment, либо varBinding, тогда
    i. Если destructuring является false (ложна), то
      1. Пусть lhsRef будет результатом вычисления lhs.(Это может быть оценено повторно.)
  h. Иначе,
    i. Утверждено: lhsKind - это lexicalBinding.
    ii. Утверждено: lhs - это ForDeclaration.
    iii. Пусть iterationEnv будет NewDeclarativeEnvironment(oldEnv).
    iv. Выполните ForDeclarationBindingInstantiation для lhs с передачей iterationEnv в качестве аргумента.
    v. Установите для LexicalEnvironment текущего контекста выполнения значение iterationEnv.
    vi. Если destructuring является false (ложна), то
      1. Утверждено: lhs связывает одно имя.
      2. Пусть lhsName будет единственным элементом BoundNames из lhs.
      3. Пусть lhsRef будет ! ResolveBinding(lhsName).
  i. Если destructuring является false (ложна), то
    i. Если lhsRef является внезапным завершением, то
      1. Пусть status будет lhsRef.
    ii. Иначе, если lhsKind является lexicalBinding, тогда
      1. Пусть status будет InitializeReferencedBinding(lhsRef, nextValue).
    iii. Иначе,
      1. Пусть status будет PutValue(lhsRef, nextValue).
  j. Иначе,
    i. Если lhsKind является assignment (присваивание), тогда
      1. Пусть status будет DestructuringAssignmentEvaluation для assignmentPattern с аргументом nextValue.
    ii. Иначе, если lhsKind является varBinding, тогда
      1. Утверждено: lhs - это ForBinding.
      2. Пусть status будет BindingInitialization из lhs с аргументами nextValue и undefined.
    iii. Иначе,
      1. Утверждено: lhsKind является lexicalBinding (лексическим связыванием).
      2. Утверждено: lhs - это ForDeclaration.
      3. Пусть status будет ForDeclarationBindingInitialization из lhs с аргументами nextValue и iterationEnv.
  k. Если status является внезапным завершением, то
    i. Установите для LexicalEnvironment текущего контекста выполнения значение oldEnv.
    ii. Если iteratorKind является async, вернуть ? AsyncIteratorClose(iteratorRecord, status).
    iii. Если iterationKind является enumerate (перечислим), то
      1. Верните status.
    iv. Иначе,
      1. Утверждено: iterationKind является iterate.
      2. Вернуть ? IteratorClose(iteratorRecord, status).
  l. Пусть result будет результатом вычисления stmt.
  m. Установите для LexicalEnvironment текущего контекста выполнения значение oldEnv.
  n. Если LoopContinues(result, labelSet) является false (ложно), то
    i. Если iterationKind является enumerate (перечислим), то
      1. Вернуть Завершение (UpdateEmpty(result, V)).
    ii. Иначе,
      1. Утверждено: iterationKind является iterate.
      2. Установите status UpdateEmpty(result, V).
      3. Если iteratorKind является async, вернуть ? AsyncIteratorClose(iteratorRecord, status).
      4. Вернуть ? IteratorClose(iteratorRecord, status).
  о. Если result.[[Value]] не является empty, установите V равным result.[[Value]].

 

14.7.5.8 Семантика времени выполнения: Оценка

ForBinding : BindingIdentifier

1. Пусть bindingId будет StringValue для BindingIdentifier.
2. Вернуть ? ResolveBinding(bindingId).

 

14.7.5.9 EnumerateObjectProperties ( O )

Абстрактная операция EnumerateObjectProperties принимает аргумент O (объект). При вызове она выполняет следующие шаги:

1. Вернуть объект Iterator (27.1.1.2), метод next которого выполняет итерацию по всем ключам со значением String перечислимых свойств O. Объект итератора никогда не доступен напрямую для кода ECMAScript. Механика и порядок перечисления свойств не указаны, но должны соответствовать правилам, указанным ниже.

Методы throw и return итератора имеют значение null и никогда не вызываются. Метод next итератора обрабатывает свойства объекта, чтобы определить, должен ли ключ свойства возвращаться как значение итератора. Возвращенные ключи свойств не включают ключи, которые являются символами. Свойства целевого объекта могут быть удалены во время перечисления. Свойство, которое удаляется перед обработкой методом next итератора, игнорируется. Если новые свойства добавляются к целевому объекту во время перечисления, не гарантируется, что новые добавленные свойства будут обработаны в активном перечислении. Имя свойства будет возвращено методом next итератора не более одного раза в любом перечислении.

Перечисление свойств целевого объекта включает рекурсивное перечисление свойств его прототипа, прототипа прототипа и так далее; но свойство прототипа не обрабатывается, если оно имеет то же имя, что и свойство, которое уже было обработано методом next итератора. Значения атрибутов [[Enumerable]] не учитываются при определении того, было ли уже обработано свойство объекта-прототипа. Имена перечислимых свойств объектов-прототипов должны быть получены путем вызова EnumerateObjectProperties, передавая объект-прототип в качестве аргумента. EnumerateObjectProperties должен получить собственные ключи свойств целевого объекта, вызвав его внутренний метод [[OwnPropertyKeys]]. Атрибуты свойства целевого объекта должны быть получены путем вызова его внутреннего метода [[GetOwnProperty]].

Кроме того, если ни O, ни какой-либо объект в его цепочке прототипов не является экзотическим прокси-объектом, экзотическим объектом с целочисленным индексом, экзотическим объектом пространства имен модуля или реализацией, предоставленной экзотическим объектом, то итератор должен вести себя так же, как итератор, заданный CreateForInIterator(O) до тех пор, пока не произойдет одно из следующих событий:

  • значение внутреннего слота [[Prototype]] для O или объекта в его цепочке прототипов изменяется,
  • свойство удаляется из O или объекта в его цепочке прототипов,
  • свойство добавляется к объекту в цепочке прототипов O, или
  • значение атрибута [[Enumerable]] свойства объекта O или объекта в его цепочке прототипов изменяется.

 

Примечание 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;
   }
}

 

Примечание 2

Список экзотических объектов, для которых не требуется, чтобы реализации соответствовали CreateForInIterator, был выбран потому, что реализации исторически различались по поведению для этих случаев и согласовывались во всех остальных.

 

14.7.5.10 Объекты Итераторы For-In

Итератор For-In — это объект, который представляет определенную итерацию над некоторым конкретным объектом. Объекты For-In Iterator никогда не доступны напрямую коду ECMAScript; они существуют исключительно для иллюстрации поведения EnumerateObjectProperties.

 

14.7.5.10.1 CreateForInIterator ( object )

Абстрактная операция CreateForInIterator принимает аргумент object (Object). Онf используется для создания объекта итератора For-In, который выполняет итерацию по собственным и унаследованным перечислимым строковым свойствам объекта object в определенном порядке. При вызове она выполняет следующие шаги:

1. Пусть итератор iterator будет ! OrdinaryObjectCreate(%ForInIteratorPrototype%, «[[Объект]], [[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%:

  • имеет свойства, которые наследуются всеми объектами итераторами For-In.
  • это обычный объект.
  • имеет внутренний слот [[Prototype]], значение которого %IteratorPrototype%.
  • никогда не доступен напрямую для кода ECMAScript.
  • обладает следующими свойствами:
14.7.5.10.2.1 %ForInIteratorPrototype%.next ( )
1. Пусть O будет значением this.
2. Утверждено: Тип(O) - это объект.
3. Утверждено: O имеет все внутренние слоты экземпляра итератора For-In (14.7.5.10.3).
4. Пусть объект object будет O.[[Object]].
5. Пусть посещён visited равно O.[[VisitedKeys]].
6. Пусть осталось remaining равно O.[[RemainingKeys]].
7. Повторите,
   а. Если O.[[ObjectWasVisited]] является false (ложно), то
      i. Пусть ключи keys будут ? object.[[OwnPropertyKeys]]().
      ii. Для каждого элемента ключа key из ключей keys выполните
         1. Если Тип(key) - Строка, то
            а. Добавьте ключ key к оставшимся remaining.
      iii. Установите для O.[[ObjectWasVisited]] значение true.
   b. Повторять, пока remaining не пусто,
      i. Пусть r будет первым элементом из remaining.
      ii. Удалите первый элемент из remaining.
      iii. Если не существует элемента v из посещенного visited, такого что SameValue(r, v) является true (истинно), то
         1. Пусть desc будет ? object.[[GetOwnProperty]](r).
         2. Если desc не является undefined, тогда
            а. Добавьте r в список посещенных visited.
            b. Если desc.[[Enumerable]] является true (истинно), вернуть CreateIterResultObject(r, false).
c. Установить объект object на ? object.[[GetPrototypeOf]]().
d. Установите O.[[Object]] на object.
е. Установите O.[[ObjectWasVisited]] на значение false.
f. Если object имеет значение null, вернуть CreateIterResultObject(undefined, true).

 

14.7.5.10.3 Свойства экземпляров итератора For-In

Экземпляры итератора For-In — это обычные объекты, наследующие свойства от внутреннего объекта %ForInIteratorPrototype%. Экземпляры итератора For-In изначально создаются с внутренними слотами, перечисленными в Таблице 42.

Internal Slot (Внутренний слот) Description (Описание)
[[Object]] Значение объекта, свойства которого повторяются.
[[ObjectWasVisited]] Значение true, если итератор вызвал [[OwnPropertyKeys]] для [[Object]], в противном случае — false.
[[VisitedKeys]] Список значений String, которые были выданы этим итератором на данный момент.
[[RemainingKeys]] Список значений String, которые должны быть созданы для текущего объекта, до итерации свойств его прототипа (если его прототип не равен null)

Таблица 42: Внутренние слоты экземпляров итераторов For-In

 

Информационные ссылки

JavaScript | Зарезервированные слова (ReservedWord)

Стандарт ECMAScript — Раздел «12.6.2 Keywords and Reserved Words» — https://tc39.es/ecma262/#prod-ReservedWord

Стандарт ECMAScript — Раздел «14.7 Iteration Statements» — https://tc39.es/ecma262/#sec-iteration-statements

Поделись записью