var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); //6
console.log(a[6]); // function(){console.log(i)}
既然循环结束后,数组a的每一项都是function(){console.log(i)},那么a[6]()输出是6是怎么实现的?难道let保存了10个状态?
之前搞错了,在外面不能输出i,以下是原来的问题
===============================
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); //6
console.log(a[6]); // function(){console.log(i)}
console.log(i); //10
a[6] = function(){console.log(i)}
而此时i=10,那么a[6]为啥不是10
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
let是块作用域声明,出了for循环就失效了~在匿名函数作用域中
log(i)引用了上层作用域的变量i,构成闭包。a[i]中保存了10个闭包,各自保留了构成闭包时变量
i的值。2个闭包栗子~
看了@同意并接受 的答案,现在我终于搞明白了,总结一下:
这个例子是很多ES6教程里面都有的,是和用var的for循环作对比,
我对这两个例子的理解是:
用let是ES6语法,for循环代码块构成一个作用域,里面的function形成闭包,function里面可以引用父作用域的变量,引用的是function被定义时的父作用域变量值,所以在每一次执行
a[i] = function () { console.log(i);}时,function都保存了当时的i值。而for使用var时,还是ES5的写法,for代码块没有形成作用域,所以里面的function不构成闭包,所以在每一次执行
a[i] = function () { console.log(i);}时,并不会保存当时i的值,所以只有当a[i]()这个函数执行时,才会使i值变现,这时,function沿着作用域链查找i的值,父作用域就是window,i的值经过十次i++,已经是10,所以a[6]()会输出10重要背景:一个知乎上关于闭包的问题(如何通俗易懂的解释javascript里面的‘闭包’?),在这个问题里,看到这样一句话之后,我如同被闪电劈中(这什么破比喻==),对于闭包概念的模糊一下子都消散了,就是这样一句话:
JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里。所以虽然我说了那么多,关键还是被被定义的作用域电光火石闪电劈中的一刹那
希望大家都能理解闭包( •̀∀•́ )
console.log(i) 应该是undefined才对吧。。。
你自己也说了a[6] = function(){console.log(i)},如果a[6]=10,那岂不是function(){console.log(i)}就是10? a[6]的值其实是这个匿名函数function(){console.log(i)},匿名函数也可以叫做函数表达式,换言之,这个表达式是a[6]的值。虽然表达式内部指示输出10,但是这不是a[6]。
如果你把 let 换成 var 的话,你会神奇的发现 a[6]() 输出 10。
这里我感觉还是 i 的作用域决定的。
因为 i 的作用域仅仅是 for 循环内, 所以在函数中调用 i 的时候,需要形成一个闭包好让外部访问。
如果 换成 var,i 的作用域是这个 js 文件的全局,在函数中调用 i 的时候是可以找到这个变量的,无需形成闭包。
还有一个概念就是 var 的变量提升问题,你可以参考下这个。