一、背景
最近在翻看以前的老书《node.js开发指南》,恰好碰到 for 循环 + setTimeout 的经典例子,于是重新梳理了思路并记录下。
二、写在前面,setTimeout 和 setInterval 的执行机制
在日常编码中,你会发现,给 setTimeout 和 setInterval 设定延迟时间往往并不准,或者干脆 setTimeout(function(){xxx},0) 也不是立马执行(特别是有耗时代码在前),这是因为 js 是单线程的,有一个事件队列机制,setTimeout 和 setInterval 的回调会到了延迟时间塞入事件队列中,排队执行。
setTimeout :延时 delay 毫秒之后,啥也不管,直接将回调函数加入事件队列。
setInterval :延时 delay 毫秒之后,先看看事件队列中是否存在还没有执行的回调函数( setInterval 的回调函数),如果存在,就不要再往事件队列里加入回调函数了。
看下面示例:
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, 1000); }
结果:1 秒之后,同时输出 5 个 5。
因为 for 循环会先执行完(同步优先于异步优先于回调),这时五个 setTimeout 的回调全部塞入了事件队列中,然后 1 秒后一起执行了。
三、正文
接下来就是那道经典的代码:
for (var i = 0; i < 5; i++) { setTimeout(function (){ console.log(i); },1000); }
结果:5 5 5 5 5
为什么不是 1 2 3 4 5,问题出在作用域上。
因为 setTimeout 的 console.log(i); 的i是 var 定义的,所以是函数级的作用域,不属于 for 循环体,属于 global。等到 for 循环结束,i 已经等于 5 了,这个时候再执行 setTimeout 的五个回调函数(参考上面对事件机制的阐述),里面的 console.log(i); 的 i 去向上找作用域,只能找到 global下 的 i,即 5。所以输出都是 5。
解决办法:人为给 console.log(i); 创造作用域,保存i的值。
解决办法一
for (var i = 0; i < 5; i++) { (function(i){ //立刻执行函数 setTimeout(function (){ console.log(i); },1000); })(i); }
这里用到立刻执行函数。这样 console.log(i); 中的i就保存在每一次循环生成的立刻执行函数中的作用域里了。
解决办法二
for (let i = 0; i < 5; i++) { //let 代替 var setTimeout(function (){ console.log(i); },1000); }
let 为代码块的作用域,所以每一次 for 循环,console.log(i); 都引用到 for 代码块作用域下的i,因为这样被引用,所以 for 循环结束后,这些作用域在 setTimeout 未执行前都不会被释放。
四、补充
在写示例代码的过程中,发现一个语法点:
function a(i){ console.log(i); } for (var i = 0; i < 5; i++) { setTimeout(a(i),1000); }
报错:
TypeError: "callback" argument must be a function at setTimeout (timers.js:421:11) ……
百度了下,原来 setTimeout 不支持传带参数的函数,可以再用一个匿名函数包装下它吧,见下面代码:
function a(i){ console.log(i); } for (var i = 0; i < 5; i++) { setTimeout(function(){ //用匿名函数包装 a(i); },1000); }
总结
以上所述是小编给大家介绍的for循环 + setTimeout 结合一些示例(前端面试题),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。
更新动态
- [ABC唱片]-《西电之声—人声》[德国版HD]WAV+CUE
- 《地狱潜者2》Reddit社区发文 呼吁大家撤销游戏差评
- 外媒评选期待已久的15款游戏:《老滚6》杳无音讯
- 不是自愿给的吗!越来越多美国人被小费文化逼疯
- 张智成.2019-你是不是张智成【海蝶音乐】【FLAC分轨】
- 群星.1999-98滚石年度最卖座主打歌刷新全纪录·新台湾男人【滚石】【WAV+CUE】
- 群星.1999-98滚石年度最卖座主打歌刷新全纪录·新台湾女人【滚石】【WAV+CUE】
- 宝藏归离任务怎么做?宝藏归离任务攻略
- 原画壁纸及美图第209期,无水印可自取
- 原画壁纸及美图第210期,无水印可自取
- 西游笔绘西行紫界演武怎么过 紫界演武通关攻略
- 西游笔绘西行沙河逐风怎么过 沙河逐风通关攻略
- 崩坏星穹铁道椒丘阵容怎么搭 崩铁椒丘组队阵容推荐
- 奥斯卡视觉奖《哥斯拉-1》,好坏参半的70周年纪念作
- 跟你走的话会被嘎蛋吗 囧图 深得自媒体新闻学的真传