变量的范围规则不一致



,所以我注意到我必须在for循环中使用let,并且不能使用const。但是,我发现可以在for-infor-of构造中使用const(下面的代码(。直觉上,我可以合理地认为这是因为for循环的实现方式不同/更原始,而其他构造的desugar进入循环中,在for for循环的顶部分配了迭代变量。

。 。
// Doesn't work
for (const i = 0; i < 3; i++) {
  console.log(i);
}
// Works
for (let i = 0; i < 3; i++) {
  console.log(i);
}
// Works
const object2 = ['a', 'b', 'c'];
for (const v of object2) {
  console.log(v);
}
// Works
const object3 = {
  a: 'a',
  b: 'b',
  c: 'c',
};
for (const v in object3) {
  console.log(v);
}

我在Mozilla MDN上唯一能找到的关于这是在for循环页面上:

此表达式可以选择使用var声明新变量 关键词。这些变量不是循环的本地,即它们在 for循环所在的相同范围。此表达式的结果是 丢弃。

这似乎也是错误的,因为如果我们对i使用let,那么ifor循环之后不再处于范围(与其他语言一致(

for (let i = 0; i < 3; i++) {
  console.log(i);
}
// Doesn't work as expected
console.log(i);

我的问题是在某个地方的规格中是否期望和定义此行为?MDN对此并不多。

是。这确实是预期的行为。

const定义了一个变量,该变量如所建议的,保持恒定。这意味着const的值无法更改。

现在,您在for循环中所做的工作正在增加" I",这被定义为常数。

for (const i = 0; i < 3; i++ /* <- this doesn't work */ ) {
    console.log(i);
}

使用for .. infor .. of,您只需绑定变量即可。

换句话说:使用for .. in/off,该变量在执行循环之前而不是在每个迭代中都会分配一次。因此,确实可以使用const

至于参考:

fordeclaration:letorconst forbinding

div>

所以我注意到我必须在内部使用循环,并且不能使用const。

否。您可以在 for循环中使用const声明即可。问题仅仅是const声明恒定绑定,因此增量i++const i上不起作用(它应该抛出异常,请确保您处于严格模式(。

如何使用const

for (const o = {index: 0, value: null}; o.index < arr.length; o.index++) {
    o.value = arr[o.index];
    doSomething(o);
}

或一个更有意义的地方:

for (const iterator = makeIterator(); !iterator.isDone(); iterator.next())
    doSomething(iterator.getCurrent());
}

直觉上,我可以合理地化,这是因为for循环的实现方式不同/更原始,而其他构造的desugar进入循环中,在for for循环的顶部分配了迭代变量。

是。在for循环中,您需要自己更新迭代变量。

  •  for([ var ]  init ; 条件;  update ({    身体} 
    变成
     [var]  init ;while(条件({    身体;     Update ;} 
  •  for( const  init>;>; 条件;  update ({    身体} 

    变成

     {    const  init ;    while(条件({        身体;         Update ;    }} 
  •  for( let  init>;>;  prinited ;  update ({    身体} 

    变得更复杂

for … infor … of循环中,您只需声明生成值的分配目标表达式。

  •  for([ var ]/ let / const  target /i>({    身体} 

    变成

     {    const _iterator =  iToble  [symend.iterator]((;    让_Result;    while(!(_结果= _iterator.next(((。完成({        [ var ]// const  target  = _Result.value;        身体;    }} 
  • for (… in enumerable)for (… of Reflect.enumerate(enumerable))相同。

我在Mozilla MDN上唯一可以找到的是for循环页面上,这似乎也是错误的。

是的,看起来该部分尚未针对ES6进行更新。

fordeclaration:letorconst forbinding

letconst中允许 for 语句。

另外,按照运行时语义语义 Spec

中提到的

forbinding的每个元素名称

此表达式for (const v in object3) {为每次迭代执行,并给出一个新的绑定

然而,使用简单的for-loop - for (const i = 0; i < 3; i++) { const i仅一旦执行 and 和>因此,它不允许您将值重新分配给一个值它

您的第一个问题已由@nulldev回答,所以我要进入第二个问题:

此表达式可以选择使用var声明新变量 关键词。这些变量不是循环的本地,即它们在 for循环所在的相同范围。此表达式的结果是 丢弃。

"这些变量不是循环的本地变量"是指var关键字创建的计数器。如果您使用let,则计数器的范围仅在此循环中。这是另一种预期的行为,因为var具有无宽的范围。是的,文档有点模棱两可。

最新更新