问题
在复习ES6的块级作用域时候又遇到了for循环的经典问题,即
var a = [];
for(var i=0;i<10;i++){
a[i] = function(){
console.log(i);
}
}
console.log(a[6]()) // 10
如何使得输出依次为1到9,使用ES6,一般这样做:
var a = [];
for(let i=0;i<10;i++){
a[i] = function(){
console.log(i);
}
}
console.log(a[6]()) // 6
我的误解
我认为上述答案也可以写成:
var a = [];
let i;
for(i=0;i<10;i++){
a[i] = function(){
console.log(i);
}
}
console.log(a[6]()) // 10
输出:10? 和想象中不一样啊?为什么不是6?
我的理由
- 块级作用域是以{}标识的,for循环应该生成十个{}子块作用域
- 每个子块{}中关联的是相应的i,即每次循环的i值
- let放在for语句内和for语句外部应该都在十个{}子块的外部吗?
请问我的错误出在哪里?
感谢@ezmo和@xialeistudio的回答,这个问题最终还是在站内搜到了。https://segmentfault.com/a/11...
@冴羽 提到,for循环中的let是标准特别定义的部分,实际上以下代码:
可以分解为:
这与“经验”不符,这是造成错误理解的根本。从C语言角度看,for中变量定义和for外定义是一样的,因为语言本身只在变量定义位置初始化一次,但js中这个for内外的let处理是有不同的内在机制的。@ezmo的回答实际上解释了这种情况,但不了解for内let有独特处理标准还是云里雾里的,谁能想到简单的for中有这样一种语法定义?