怎么理解for循环中用let声明的迭代变量每次是新的变量?

背景

最近在总结基础知识,然后看了阮一峰老师的es6教程,其中谈及let以及块级作用域的时候,举了一个经典的例子,代码如下:

var a = [];for (var i = 0; i < 10; i++) {  // 作用域a
  a[i] = function () {    // 作用域b
    console.log(i);
  };
}
a[6](); // 10

因为es5不存在块级作用域,所以迭代变量i泄露了,然后对于a数组内每一个函数内的i都是向上查询作用域a的,所以结果是10。这个没问题。

下面的例子是用let来声明迭代变量的

var a = [];for (let i = 0; i < 10; i++) {
  a[i] = function () {    console.log(i);
  };
}
a[6](); // 6

老师是这样解释的

上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。

疑问
我想不通每一次循环的i其实都是一个新的变量这个过程是怎么样的,如果我理解为每次迭代都是新的一个块级作用域,那么迭代变量的迭代(i++)是如何传递给下一个块级作用域呢?

自知之明
虽然我知道结果,也知道这样的问题是转牛角尖,就是好奇问问。希望各路英雄指点迷津。


ABOUTYOU
浏览 1118回答 1
1回答

慕妹3242003

这是在for语句中的var与let的差异:for (let x...)的循环在每次迭代时都为x创建新的绑定以下用代码直接看会比较容易的理解。这个改进主要是为了要解决在for语句中的闭包结构的问题。原来的使用var的代码,与去糖(desugar)后来看它在执行时是这样的模拟代码://原来代码for&nbsp;(var&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;10;&nbsp;i++)&nbsp;{&nbsp;setTimeout(()=>console.log("i:",i),&nbsp;1000);&nbsp;}//&nbsp;不需要加区块符,因为区块也不会影响var&nbsp;i; i&nbsp;=&nbsp;0;if&nbsp;(i&nbsp;<&nbsp;10) &nbsp;&nbsp;&nbsp;&nbsp;setTimeout(()=>console.log("i:",i),&nbsp;1000); &nbsp;&nbsp;&nbsp;&nbsp;i++;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(i&nbsp;<&nbsp;10) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setTimeout(()=>console.log("i:",i),&nbsp;1000); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i++;//...而使用了let后,会有块级作用域的影响,原来的代码与执行时的去糖模拟代码如下://&nbsp;原来代码for&nbsp;(let&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;10;&nbsp;i++)&nbsp;{&nbsp;setTimeout(()=>console.log("i:",i),&nbsp;1000);&nbsp;}//&nbsp;用区块符区分每次循环的语句//&nbsp;每次for语句开始,i指定为一个全域刻度__status,这只是方便说明而已//&nbsp;__status会记录for语句i最后的值{&nbsp;let&nbsp;i; &nbsp;&nbsp;i&nbsp;=&nbsp;0; &nbsp;&nbsp;__status&nbsp;=&nbsp;{i}; } {&nbsp;let&nbsp;{i}&nbsp;=&nbsp;__status;&nbsp;&nbsp;if&nbsp;(i&nbsp;<&nbsp;10) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setTimeout(()=>console.log("i:",i),&nbsp;1000); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__status&nbsp;=&nbsp;{i}; }&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;let&nbsp;{i}&nbsp;=&nbsp;__status; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(i&nbsp;<&nbsp;10) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setTimeout(()=>console.log("i:",i),&nbsp;1000); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__status&nbsp;=&nbsp;{i}; &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;//...
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript