读一下程序,判断输出结果,并分析原因
var apples = ["apple1", "apple2", "apple3"];
for (var i = 0, funs = []; i < 3;i ++){
funs[i] = function(){
console.log(apples[i]);
}
}
funs[0]();
funs[1]();
funs[2]();
读一下程序,判断输出结果,并分析原因
var apples = ["apple1", "apple2", "apple3"];
for (var i = 0, funs = []; i < 3;i ++){
funs[i] = function(){
console.log(apples[i]);
}
}
funs[0]();
funs[1]();
funs[2]();
apple3*3,这个都不是闭包,只是变量作用域问题,你的函数体内执行的console.log(apples.[i]),i是一个变量,js中不存在块级别变量,所以i在循环后还在,i循环后是几?
块级作用域的问题 三个 function 共享同一个 i 值
还有一个考察细心 跳出循环条件是 i<3
不成立 也就是 i=3
而 a[3] 是 undefined
所以是
undefined
undefined
undefined
其实把它拆开就简单易懂了
循环后得到的是:
i=>3;
funs[0] = function (){
console.log(apples[i]);
};
funs[1] = function (){
console.log(apples[i]);
}
funs[3] = function (){
console.log(apples[i]);
}
apples[3]不存在,所以全部为undefined
闭包后,
console.log(apples[i]);
里的i与外部循环上的i无关,故在执行
funs[0]();
等代码时,闭包里的i会一直undefined,故最后输出的全是undefined。
我也来回答下 个人理解:
由于for不会新建一个块级作用域(除let),所以变量i是属于上一级(在这里就是全局)作用域,而每个作用域会有个活动对象(AO),负责存储管理这些变量。
一开始 ao = {apples: [...]}
, 执行for循环时,ao.i = 0
, 并对ao.apples遍历成员进行事件监听,循环结束,此时ao.i = 3
当事件触发时,会去逐级的作用域找i,找到最近的作用域为ao,所以会执行console.log(ao.apples[3])
因为 funs[i]这个函数是被异步执行的,所以在你调用这个函数之前,整个循环就已经结束了,这个时候再沿着作用域链由内到外查找变量i,此时的i就全都变成了不满足循环条件的3了,所以会输出三个undefined
8 回答4.7k 阅读✓ 已解决
6 回答3.4k 阅读✓ 已解决
5 回答2.8k 阅读✓ 已解决
5 回答6.3k 阅读✓ 已解决
4 回答2.3k 阅读✓ 已解决
4 回答2.8k 阅读✓ 已解决
3 回答2.5k 阅读✓ 已解决
闭包是一个自带运行环境的函数,题中的闭包function函数本地作用域中没有i这个变量,只能沿着作用域链往上查找,而上级作用域中的i最终为3。
将代码改成这样的话,就可以分别输出。
为什么这样就可以了呢?
因为把i每次的值都放到上级作用域链里面了。