for,for-in和for-of循环中变量的范围规则不一致 [英] Inconsistent scope rules of variables in for, for-in and for-of loops

查看:215
本文介绍了for,for-in和for-of循环中变量的范围规则不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

//工作
for(let i = 0; i< 3; i ++){
console.log(i);
}

//作品
const object2 = ['a','b','c'];
for(const v of object2){
console.log(v);
}

//工作
const object3 = {
a:'a',
b:'b',
c:'c' ,
};
for(const v in object3){
console.log(v);
}

我在Mozilla MDN上唯一能找到的就是 for loop page:


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


这似乎也是错误的,因为如果我们使用让为然后 i for 循环之后不再在范围内(与其他语言一致)

  for(let i = 0; i< 3; i ++){
console.log(i);
}
//无法按预期工作
console.log(i);

我的问题是这个行为是否是预期的并且在某个地方的规范中定义了? MDN对此没有太多说明。

解决方案


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


否。您可以在中为循环使用 const 声明就好了。问题只是 const 声明了一个常量绑定,因此增量 i ++ 对<$ c $不起作用c> 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 ;  condition ;  update ){
    body
    }



    成为

     [var]  init ; 
    while( condition ){
    body ;
    更新; (b 初始; 条件; 更新){
    正文
    }

    变为

     {
    const init ;
    while( condition ){
    body ;
    更新;
    }
    }


  •  for( let   init ; 条件; 更新){
    正文
    }

    成为更复杂的内容




对于中的...的循环中的,只是声明生成值的赋值目标表达式。




  •  for([ var ] /  /  const  目标  iterable ){
    body
    }

    变为

     {
    const _iterator = < I>迭代的[Symbol.iterator]();
    让_result;
    while(!(_ result = _iterator.next())。done){
    [ var ] / / const target = _result.value;
    body ;
    }
    }


  • for(... in enumerable)相同((Reflect.enumerate(可枚举))





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


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


So I noticed that I have to use let inside a for loop, and cannot use const. However, I found that I can use const inside the for-in and for-of constructs (code below). Intuitively I can rationalize that this is because the for loop is implemented differently/is more primitive, whereas the other constructs desugar into for loops where the iterating variable is assigned at the top of the for loop.

// 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);
}

The only thing I could find on Mozilla MDN about this was on the for loop page:

This expression may optionally declare new variables with the var keyword. These variables are not local to the loop, i.e. they are in the same scope the for loop is in. The result of this expression is discarded.

Which also seems wrong, because if we use a let for i then i is no longer in scope after the for loop (which is consistent with other languages)

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

My question is whether this behaviour is expected and defined in the spec somewhere? MDN doesn't say much about this.

解决方案

So I noticed that I have to use let inside a for loop, and cannot use const.

No. You can use a const declaration in a for loop just fine. The problem just is that const declares a constant binding, so an increment i++ doesn't work on const i (it should throw an exception, make sure you're in strict mode).

An example of how to use const:

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

Or one where it makes more sense:

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

Intuitively I can rationalize that this is because the for loop is implemented differently/is more primitive, whereas the other constructs desugar into for loops where the iterating variable is assigned at the top of the for loop.

Yes. In a for loop, you need to take care of updating the iteration variables yourself.

  • for ([var] init; condition; update) {
        body
    }

    becomes

    [var] init;
    while (condition) {
        body;
        update;
    }

  • for (const init; condition; update) {
        body
    }

    becomes

    {
        const init;
        while (condition) {
            body;
            update;
        }
    }

  • for (let init; condition; update) {
        body
    }

    becomes something more complicated

In for … in and for … of loops, you just declare an assignment target expression for the produced value.

  • for ([var]/let/const target of iterable) {
        body
    }

    becomes

    {
        const _iterator = iterable[Symbol.iterator]();
        let _result;
        while (!(_result = _iterator.next()).done) {
            [var]/let/const target = _result.value;
            body;
        }
    }

  • for (… in enumerable) is just the same as for (… of Reflect.enumerate(enumerable)).

The only thing I could find on Mozilla MDN about this was on the for loop page, which also seems wrong.

Yes, looks like that section hasn't yet been updated for ES6.

这篇关于for,for-in和for-of循环中变量的范围规则不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆