读一下程序,判断输出结果,并分析原因
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]();
Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
闭包是一个自带运行环境的函数,题中的闭包function函数本地作用域中没有i这个变量,只能沿着作用域链往上查找,而上级作用域中的i最终为3。
将代码改成这样的话,就可以分别输出。
为什么这样就可以了呢?
因为把i每次的值都放到上级作用域链里面了。
apple3*3,这个都不是闭包,只是变量作用域问题,你的函数体内执行的console.log(apples.[i]),i是一个变量,js中不存在块级别变量,所以i在循环后还在,i循环后是几?
闭包解决,经典问闭包的方式,
i是全局变量,在调用时其值为3,所以全部是undefined,目前的基本可以采用let来解决了undefined
undefined
undefined
应该是这样的。
块级作用域的问题 三个 function 共享同一个 i 值
还有一个考察细心 跳出循环条件是
i<3不成立 也就是i=3而 a[3] 是
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
闭包后,
里的i与外部循环上的i无关,故在执行
等代码时,闭包里的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