for (let i = 0; i < 5; i++) {
a[i] = function() {
console.log(i)
}
}
a[2]() //2
i为什么不是undefined,for循环里面我只是创建了一个函数,为什么我执行a[2]的时候还是能拿到i的值
for (let i = 0; i < 5; i++) {
a[i] = function() {
console.log(i)
}
}
a[2]() //2
i为什么不是undefined,for循环里面我只是创建了一个函数,为什么我执行a[2]的时候还是能拿到i的值
你这不是创建了5个函数吗?
a[0] = function(){
console.log(0);
}
a[1] = function(){
console.log(1);
}
a[2] = function(){
console.log(2);
}
.....
let 关键字会将for循环形成闭包,从console.log(i) 这里的i就是0,1,2,3,4。那么你执行就会打印出相应的值
可以变相看:
var i,
a = [];
for(i=0; i<5; i++){
(() => {
a[i] = () => { console.log(i); } //这里面的所有i都是外面传入进来的,循环一次创建一次函数。
})(i);
}
这个是let
用法问题,首先需要指出的是不管怎么样都不会是undefined
:
如果for
循环中使用的是var
声明i
,那么i
是一个全局变量,for
循环后i
值为5,执行任意一个a
中的函数结果都是打印5
问题中使用的是let
声明,let
具有块级作用域,每个i
都是其对应循环的局部变量。你执行a[2]
能拿到值的原理就是闭包,可以获取每一次循环所代表的块级作用域中的局部变量
es6中每一次循环都是一个独立的块级作用域,块级作用域中的变量被全局变量引用了,当前这个块级作用域不销毁,所以在全局作用域,a[2]函数执行的时候,能够往a[2]函数定义的上级作用域找到i
let是es6中的东西;在es6中for循环会形成一个独立的块级作用域;let具有块级作用域,每个i都是其对应循环的局部变量。你执行a[2]能拿到值的循环的值,可以获取每一次循环所代表的块级作用域中的局部变量
10 回答11.6k 阅读
2 回答3.1k 阅读✓ 已解决
3 回答2.7k 阅读✓ 已解决
2 回答2.1k 阅读✓ 已解决
4 回答2.1k 阅读✓ 已解决
3 回答1.2k 阅读✓ 已解决
3 回答1.8k 阅读✓ 已解决
因为let具有块级作用域的特性,因此i只会在当前循环有效。
实际上你的循环创建了5个块级作用域,每一个i值都只在当前的块级作用域中有效果。
你的代码等同于如下:
这里就很容易能看出:
实际上let的存在让每一个i值都保存在了一个闭包中。因此这个循环创建了5个闭包。
而a数组里则保存了一堆函数,每一个函数都访问了对应的闭包中的i值。
所以i的值肯定是存在的而不undefined。