ECMAScript 2015:for 循环中的 const

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 的完整实现,具有各种行为两个循环变体;我也无法在标准中找到具体点,因此将不胜感激。

你的第二个例子绝对不能工作,因为 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.";
}

for 循环中 const 并不是完全不允许的。只有 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 在阅读了 ES2015 规范后给出了一个 SyntaxError(虽然我确信 Mozilla 的聪明人是正确的),它似乎应该引发一个异常:

Create a new but uninitialized immutable binding in an Environment Record. The String value N is the text of the bound name. If S is true then attempts to access the value of the binding before it is initialized or set it after it has been initialized will always throw an exception, regardless of the strict mode setting of operations that reference that binding. S is an optional parameter that defaults to false.

以下 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 循环将不起作用:

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;
        …
    }
}

为简单起见,我忽略了 a 表达式有一个带 e 的 TDZ,以及循环中的各种 __it.return()/__it.throw(e) 调用过早退出(breakthrow 在正文中)。

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

基本等同于

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

for 循环中的 const 声明不会在每次循环迭代中都重新声明(并且初始化程序不会重新执行)。除非你在第一次迭代中 break,否则你的 i += 将在此处抛出。