在 ES2015 中 for 循环计数器可以是 const 声明吗?

una*_*ist 3 javascript for-loop ecmascript-6

首先,let可用于循环计数器声明。这也在MDN 中进行了描述

for(let i = 0; i < 2; ++i) {
  setTimeout(function(){
    document.write(i + "<br>");
  }, 0);
}
Run Code Online (Sandbox Code Playgroud)

结果:

0
1
Run Code Online (Sandbox Code Playgroud)

由于let使用了,i可以在for块内部更改值。

for(let i = 0; i < 2; ++i) {
  setTimeout(function(){
    document.write(i + "<br>");
  }, 0);
  i = 123; // I want to block this assignment!!
}
Run Code Online (Sandbox Code Playgroud)

所以我考虑使用const而不是let.

for(const i = 0; i < 2; ++i) { // throws Assignment to constant variable
  setTimeout(function(){
    document.write(i + "<br>");
  }, 0);
  i = 123; // not here...
}
Run Code Online (Sandbox Code Playgroud)

但是,此代码会抛出Assignment to constant variable.(在 Chrome 53.0.2773.0 中)。

我希望这个循环像第一个let例子一样循环两次,但i只在内部 for 循环迭代中使计数器可写。

我认为这是允许的,因为ECMA-262 §13.7.4.7似乎提到了这种情况,因为If isConst is true, ...,但我在 MDN 和其他站点中找不到这种用法(或实现状态)。Kangax 的表包含针对letbindings 的测试,但不包含针对bindings 的测试const

le_*_*e_m 5

我测试了它(在 Firefox 中)并且 const 绑定根据规范工作:

let i = 0;
for (const len = 3; i < len; i++) {
  console.log(i);
}

// From https://kangax.github.io/compat-table/es6/#test-const
for (const baz = 0; false;) {}

// Yay, a const counter! ...uh
for (const counter = {i: 0}; counter.i < 3; counter.i++) {
  console.log(counter.i);
}
Run Code Online (Sandbox Code Playgroud)

虽然它可能不是特别有用...

为什么有效?标准指出:

  5. For each element dn of boundNames do
    a. If isConst is true, then
      i.  Perform loopEnv.CreateImmutableBinding(dn, true).
Run Code Online (Sandbox Code Playgroud)

...whereboundNames指的是const绑定。正如您所看到的,该标准允许const“循环计数器”,但并没有说您以后可以重新分配(增加)它们(实际上,这不起作用)。