for,for-in和for-of循环中变量的范围规则不一致 [英] Inconsistent scope rules of variables in for, for-in and for-of loops
问题描述
所以我注意到我必须在中使用
循环,并且不能使用 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 asfor (… 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屋!