setTimeout经典案例
来源:互联网 发布:用java开发的网站 编辑:程序博客网 时间:2024/05/29 07:14
在日常编码中,你会发现,给 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); }
- setTimeout经典案例
- setTimeout 与setInterval 用法案例
- 经典案例
- javascript中setTimeout函数使用案例
- setTimeout 延时定时器的使用小案例
- 经典问题:向setTimeout传递函数参数
- [转载]经典问题:向setTimeout传递函数参数
- 经典问题:向setTimeout传递函数参数
- 嵌套查询经典案例
- C经典案例
- log4j经典案例
- SNS经典案例 分享
- 经典处事案例
- 接口的经典案例
- oracle 经典查询案例
- 数据查询经典案例
- 数据挖掘经典案例
- C++继承经典案例
- 物联网感知层进入技术创新爆发期
- 【难容异见,常被他人的言行激怒】…
- Linux安装PHP curl拓展
- MySQL性能优化总结
- 【如果不时时和恋人黏在一起,我就…
- setTimeout经典案例
- 【明明有很多朋友,为什么还是寂寞…
- 项目集成讯飞语音识别
- 【大家都说要「创新」,但具体怎么…
- 【小学期间孩子的差距是如何拉开的…
- 数据库事务
- 【他是真心还是只想玩玩?两招看穿…
- 【不是有理念,消费者就该买单。3…
- 物联网技术助力创新城市管理、加强社会治理