javascript - 一道面试题-求解
怪我咯
怪我咯 2017-04-11 10:36:50
[JavaScript讨论组]

读一下程序,判断输出结果,并分析原因

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]();
怪我咯
怪我咯

走同样的路,发现不同的人生

全部回复(9)
迷茫

闭包是一个自带运行环境的函数,题中的闭包function函数本地作用域中没有i这个变量,只能沿着作用域链往上查找,而上级作用域中的i最终为3。

var apples = ["apple1", "apple2", "apple3"];
for (var i = 0, funs = []; i < 3;i ++){
    funs[i] = (function(x){
        return function(){
        console.log(apples[x]);
        }
    })(i);
}
funs[0]();
funs[1]();
funs[2]();

将代码改成这样的话,就可以分别输出。
为什么这样就可以了呢?

因为把i每次的值都放到上级作用域链里面了。

巴扎黑

apple3*3,这个都不是闭包,只是变量作用域问题,你的函数体内执行的console.log(apples.[i]),i是一个变量,js中不存在块级别变量,所以i在循环后还在,i循环后是几?

PHPz

闭包解决,经典问闭包的方式,i是全局变量,在调用时其值为3,所以全部是undefined,目前的基本可以采用let来解决了

大家讲道理

undefined
undefined
undefined

应该是这样的。

黄舟

块级作用域的问题 三个 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

PHP中文网

闭包后,

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

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号