var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
我知道let定义的变量具有块级作用域,但还是不明白为什么输出的是6,求解释原理。
另外这里也有闭包形成吧?
Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
let定义的变量i具有块级作用域,作用域是for循环所包含的语句块。
这个for循环最终执行了10次,实际上会产生10个互相平行的块级作用域。在每个作用域里面,i的值分别是0,1,2,..,8,9。
当调用a[6]时,执行到console.log(i)这行语句时,解释器会沿着作用域链寻找i的值,结果向上一层就是这10个平行作用域中的第7个,其中i的值为6,于是就打印出了6。
这段代码如果被翻译成ES5代码,应该如下:
实际上,使用babel 6.6.5 babel-preset-es2015 6.6.0 的转换结果如下:
i是for循环这个作用域的局部变量,每次进入for循环都会重新创建,所以i对应的值为1、2...6。我理解,这里应该是有形成闭包的,闭包其实就是函数持有其外层作用域的引用,能够访问外层作用域的变量。如果for循环里面没有那个打印函数,for语句执行完之后,这个块级作用域应该会销毁掉。由于循环中的函数,for执行完之后i并没有回收,这和通常的函数级作用域嵌套道理貌似是一样的。
没看出什么闭包,也没觉得跟 let 有啥关系。就普通的一个循环,把表达式储存在数组中:
所以
a[6]应该是表达式function () {console.log(6)}本身。所以结果是:(function () {console.log(6)})(),那自然就是 6 咯。这不是闭包。
在你读取i的值时,循环早已结束,i已经是6了。