for循环中使用let,最后一次循环结束后i值为什么不进行一次自加

var testVar;
for(var i=0;i<3;i++){
    testVar=function(){
    console.log(i)
    };
}
testVar(); // 结果为3
let testVar;
for(let i=0;i<3;i++){
    testVar=function(){
    console.log(i)
    };
}
testVar(); // 结果为2

testVar中的闭包中保存了i的引用,而不是i当前的值,而i值在最后一次循环结束后执行了一次i++变成了3。
但是let的for循环,最后一次循环,应该也是保存了i的引用,而这个i在最后一次循环结束后也应该执行一次i++,也应该变成3。但是输出为什么是2。
由于对闭包的理解不同,而闭包不是这个问题的重点,所以我又换了个方式重新提问,如下------------------------
testVar()返回的是这个函数被调用的时候的i值,用var的for循环,最后一次循环i值是2,由于被调用的时候循环已经结束,i值要进行一次i++,所以变成了3;
而let的for循环,理论上来讲,也是这样的过程,最后也要进行i++,为什么还是2?

阅读 6.2k
2 个回答
var的for循环我明白

不,你不明白

你的代码相当于:

var testVar,i;
for(i=0;i<3;i++){
    testVar=function(){
    console.log(i)
    };
}
testVar();

那么你告诉我,为什么不是3?跟闭包一点关系没有,仅仅因为i 是全局变量,等你testVar()i已经变成了3.

ES6 let 的代码相当于

let testVar;
for(let i=0;i<3;i++){
    let k=i;
    testVar=function(){
      console.log(k)
    };
}
testVar(); 

i=3的时候,根本不会执行{}里的代码,所以当然是 2,而且这里的i,k都处于块级作用域,{}之外根本无法访问。与var是有完全区别的。

es5 没掌握好不建议学es6,先巩固下var的变量提升和闭包吧,es5 没有块级作用域在学 ES6 之前就应该知道的。

区别就在于 let 使得每次程序进入花括号就产生了一个块级作用域,因此打印的i就是在这个循环中i最后的值2,在循环之外i是无法访问到的。
而使用var是会产生变量声明提升,所以打印的i是最后的全局的i,3。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题