javascript - 刚看了一个闭包的题,拿出来大家看看好多点的哈哈
迷茫
迷茫 2017-04-10 15:18:25
[JavaScript讨论组]
for(var i = 6; i--;) {
    setTimeout(
        function() { 
            console.log(i);
    }, 0);
}
迷茫
迷茫

业精于勤,荒于嬉;行成于思,毁于随。

全部回复(5)
怪我咯

因为没有用闭包,内部的匿名函数无法保存i的值,导致在循环走完了,i成-1的时候,才会被log出,所以是6个-1,这样改写:

for(var i = 6; i--;) {
    setTimeout(
        (function(j) { 
            console.log(j);
    })(i), 0);
}

改写过后,每一个匿名函数被声明的时候,被放入执行队列,同时,i的值也被传入,即被保存,所以console.log()的结果是正常的 5~0 。

这题的关键点:

闭包的正确使用
setTimeout会延迟内部函数至执行队列空闲时执行函数
(其实这题是否将函数放入setTimeout没差~)

为了体现setTimeout的存在感,咱们改写示例:

setTimeout(
    function() { 
        console.log(i);
}, 0);
for(var i = 6; i--;) {

}

这里的结果大家可以看看是什么~   
是undefined还是-1 ~
巴扎黑

其实开始我在for循环就卡了,因为没有终止条件,这里省略了第二个参数,实际在i为0的时候就相当于false终止了循环;
然后我跑了

for(var i = 6; i--;) {
    console.log(i)
}

发现输出的最后一个数字是0而不是-1 但是实际上在for循环外执行console.log(i)的时候输出的值为-1。

var i = 0;
if (i--) {
    console.log("=="); //没有执行
}
console.log(i); //-1

然后就是setTimeout这个关键:"setTimeout(fn, 0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,尽可能早得执行。它在"任务队列"的尾部添加一个事件,因此要等到同步任务和"任务队列"现有的事件都处理完,才会得到执行。"

基础不行TT

黄舟

⊙▂⊙,刚开始以为会一直循环下去死机呢!因为没看懂 i-- ,所以这道题让我受益的就是 i-- 这个判断了,以前都是写什么小于或大于什么的条件判断。

其实setTimetout里面也有些玄机的,它可以用来实现异步编程
setTimeout(
function() {
console.log(i);
}, 0);

没循环一次,都要把那个匿名函数添加到事件队列中,然后接着又下一次循环,一直到跳出循环前,事件队列中的所有匿名函数都没被添加到事件循环中执行,跳出循环后,也就是事件循环空闲了,才依次执行队列中匿名函数,而此时i的值已经是 -1了 ,所以每个匿名函数都是输出 -1。

大家讲道理

首先我觉得i--判断条件确实有点意思,以前很少这样用,当然这样玩玩就好了,代码中还是写>或<其他人更容易理解。
另外,关于for循环中的setTimeout这个问题,首先我们应该明确:

setTimeout({//...}, 0)表示将这个任务在主线程最早可得的空闲时间执行
这里,也就是在for循环之后执行。所以代码大致可以理解为:

for(var i = 6; i--;) {

}
// i: -1
console.log(i);
console.log(i);
console.log(i);
console.log(i);
console.log(i);
console.log(i);
PHP中文网

看了楼上的评论感觉受益匪浅啊.

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

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