定时器基础
定时器功能主要由setTimeout()和setInterval()这两个函数来完成,它们的内部运行机制完全一样,区别在于前者指定的代码是一次性执行,后者则为反复执行。以下主要讨论setTimeout()。
定义:
var timerId = setTimeout(func|code, delay)
第一个参数func|code是将要推迟执行的函数名或者一段代码,第二个参数delay是推迟执行的毫秒数。
需要注意的地方:如果第一个参数是写的一段代码,必须是字符串的形式,因为引擎内部使用eval函数,将字符串转为代码。console.log("start");
setTimeout('console.log(123)',1000);//注意:这里是字符串
console.log("end");
//输出结果
start
end
123
console.log("start");
setTimeout(console.log(123),1000);//注意:这里不是字符串
console.log("end");
//输出结果
start
123
end
理解定时器
setTimeout('console.log(123)',1000);
这段代码从宏观思想上理解是过1000毫秒后在控制器上输出123,从微观上来讲1000毫秒并不是程序执行时间,而是加入任务队列的时间。
我们知道执行栈中的代码(同步任务),总是在读取"任务队列"(异步任务)之前执行。若是执行栈的执行时间太长,定时器就不会准确无误的按照预期的时间去执行定时器里面的代码。
以setTimeout(func,0)为例
他并不是马上就可以执行func里的代码,而是等执行栈执行完毕后,立即执行(0毫秒间隔)指定的回调函数。
再举个例子
setTimeout('console.log(1)',1000);
setTimeout('console.log(2)',1000);
这段代码是过1000毫秒后打印1,再等1000毫秒继续打印2吗?不是,正确的答案是:过1000毫秒后同时打印1和2
我们可以想象一下这个执行过程,首先遇到第一个定时器,告诉异步模块等待1000毫秒加入任务队列,遇到第二个定时器,同样等待1000毫秒加入任务队列。等到执行栈为空,进入任务队列中拿任务,遇到第一个console,输出,这要不了多久,几乎无时差又拿到第二个console
两个定时器等待时间相同,但第一个定时器回调还是先进入任务队列,所以先触发,这也印证了任务队列先进先出的规则。
定时器的注意点和一些冷知识
- 定时器的返回值是一个number值
var timer=setTimeout(function(){
console.log(123)
},1000);
console.log(timer);
- setTimeout()可以接收更多的参数,从第三个参数开始,依次用来表示第一个参数(回调函数)传入的参数,例如:
setTimeout(function(a,b){
console.log(a+b);//这里打印的是:7
},1000,3,4);
- clearInterval()和clearTimeout()其实是通用的。
var timer=setTimeout(function(){
console.log(123)
},1000);
clearInterval(timer)//注意:这里没有用clearTimeout()
- setInterval(),setTimeout() 方法是浏览器 window 对象提供,所以第一个参数函数中的this指向window对象,这跟变量的作用域有关:
var a=1;
var obj={
a:2,
b:function(){
setTimeout(function(){
console.log(this.a);//这里返回的是:1;
},2000);
}
};
obj.b();
可以做做题,这样你会更强 [滑稽]
链接: 从一道看似简单的面试题重新理解JS执行机制与定时器.