Подтвердить что ты не робот

ECMAScript 2015: const для циклов

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

for (const e of a)

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

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

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

4b9b3361

Ответ 1

Работает следующий цикл:

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

Ответ 2

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

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 я = 0; я < a.length; я += 1) …

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

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

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

Ответ 3

Второй пример должен определенно не работать, потому что 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, будет.

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

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 истинно, попытки получить доступ к значению привязки до того, как он будет инициализирован или установлен после его инициализации, всегда будут генерировать исключение, независимо от строгой настройки режима операций, которые ссылаются на эту привязку. S - необязательный параметр, который по умолчанию имеет значение false.