ECMAScript 2015: const in for loops


какой из двух (или ни один/ оба) фрагментов кода ниже должен работать в полной реализации ECMAScript 2015:

for (const e of a)

for (const i = 0; i < a.length; i += 1)

насколько я понимаю, первый пример должен работать, потому что e инициализируется для каждой итерации. Не должно ли это также иметь место для i во втором варианте?

Я в замешательстве, потому что существующие реализации (Babel, IE, Firefox, Chrome, ESLint), похоже, не являются последовательные и имеют полную реализацию const, С различным поведением двух вариантов цикла; я также не могу найти конкретную точку в стандарте, так что это было бы очень ценно.

3   51   2015-08-13 14:52:35

3 ответа:

работает следующий цикл for-of:

for (const e of a)

спецификация ES6 описывает это как:

ForDeclaration: LetOrConst ForBinding

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-in-and-for-of-statements-static-semantics-boundnames

императив для цикла не будет работать:

for (const i = 0; i < a.length; i += 1)

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

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-statement-runtime-semantics-labelledevaluation

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

for (const e of a) …

в основном эквивалентно

{
    const __it = a[Symbol.iterator]();
    let __res;
    while (__res = __it.next() && !__res.done) {
        const e = __res.value;
        …
    }
}

для простоты я проигнорировал, что есть TDZ с e на a выражение, и различные __it.return()/__it.throw(e) вызовы в случае преждевременного завершения цикла (break или throw в теле).

for (const i = 0; i < a.length; i += 1) …

в основном эквивалентно

{
    const i = 0;
    while (i < a.length) {
        …
        i += 1;
    }
}

в отличие от let, a const декларации for цикл не объявляется повторно в каждой итерации цикла (и инициализатор не выполняется повторно в любом случае). Если только ты break в первой итерации, ваш i += бросит здесь.

ваш второй пример определенно не должен работать, потому что i объявляется один раз, а не на каждой итерации это просто функция того, как работает эта категория циклов.

вы можете попробовать это в обычном браузере:

for (var i = 0, otherVar = ""; i < [1,2,3,4].length; i += 1){
  console.log(otherVar)
  otherVar = "If otherVar was initialized on each iteration, then you would never read me.";
}

это не тот случай, когда const полностью запрещен в for петли. Только for это изменит const is.

они действительны:

for(const i = 0;;){ break } 
for(const i = 0; i < 10;){ break; } 

это неверный:

for(const i = 0;;){ ++i; break; } 
for(const i = 0;;++i){ if(i > 0) break; }

Я не уверен почему Firefox дает SyntaxError после прочтения спецификации ES2015 (хотя я уверен, что умные люди в Mozilla правы), похоже, что он должен вызвать исключение:

создайте новую, но неинициализированную неизменяемую привязку в записи среды. Строковое значение N-это текст связанного имени. Если S имеет значение true, то попытки доступа к значению привязки до ее инициализации или установить его после инициализации всегда будут вызывать исключение, независимо строгого режима операций, которые ссылаются на эту привязку. S-Это необязательный параметр, который по умолчанию имеет значение false.