1.背景介绍
什么是定时器?
JS提供了一些原生方法来实现延时去执行某一段代码。
我们在JS中一般会使用以下两种定时器
setTimeOut( ) setInterval( )
setTimeout
暂停指定的毫秒数后执行指定的代码
setInternval
间隔指定的毫秒数不停地执行指定的代码。
2.知识剖析
setTimeOut:
语法:setTimeOut(code,millisec)
这个方法所有浏览器都支持,setTimeout( ) 是属于 window 的 method, 但我们都是略去 window 这顶层物件名称, 这是用来设定一个时间, 时间到了, 就会执行一个指定的 method。
code:必需,要调用的函数或执行的JavaScript代码;
millisec:必需,在执行代码前需等待的毫秒数。
该定时器只执行一次,若需要多次调用,可使用setInterVal()或让code自身再次调用setTimeOut()。
返回值: 一个可以传递给 Window.clearTimeOut() 从而取消对 code 的周期性执行的值。
清除定时器:
语法:clearTimeOut(str)
为了更方便的清除指定定时器,就必须在用定时器的时候,定义一个变量来记录定时器的返回值。比如:
var str = setTimeOut(test,1000);
setInterVal:
语法:setInterval(code,millisec)
setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。setInterval() 方法会不停地调用函数,直到clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。
code:必需。要调用的函数或要执行的代码串。
millisec:必须。周期性执行或调用 code 之间的时间间隔,以毫秒计。
返回值: 一个可以传递给 Window.clearInterval() 从而取消对 code 的周期性执行的值。
清除定时器:方法与 setTimeOut() 相同。
语法:clearInterval()
这两种定时器,设置方法有区别,但是清除方法是等效的,就是无论你设置的定时器是哪一种 都可以使用上边任意一种清除代码清除掉。
3.常见问题
setInterval多次调用后执行频率为什么越来越快?
当我们在启动一个定时器时,电脑会为我们开启一个定时器,当我们再次用同一个名字开启定时器时,电脑会再开另外开启一个定时器,与先前开启的定时器无关,我们所谓的定时器的名字,它只是一个变量而已,并不是定时器的名字,它的功能是清定时器用的,也就是通过clearInterval(变量)使定时器停止运行。
<!---- setInterval() 的运行模式是按照指定的周期(以毫秒计)来调用函数或计算表达式。
这就使得在某个多次执行或者重复执行事件中创建的setInterval()都会独立的保留下来。 ---->
4.解决方案
方案一:每次调用前清除定时器
var timer;
var flashStart = function () {
clearTimeout(timer);
timer = setInterval(function(){
/ 代码块…… /
},1000);
};
方案二:给定时器加一个开关
var switch = 'off';
var timer;
var function test(){
if(switch === 'off'){
timer = setInterval(function(){
/ 代码块…… /
},1000);
}
switch = 'on';
}
5.编码实战
6.扩展思考
若参数 millisecs 为 0 ,会发生什么?
Javascript是单线程执行的,也就是无法同时执行多段代码,当某一段代码正在执行的时候,所有后续的任务都必须等待,形成一个队列,一旦当前任务执行完毕,再从队列中取下一个任务。这也常被称为“阻塞式执行”。
如果代码中设定了一个setTimeout,那么浏览器便会在合适的时间,将代码插入到任务队列中,如果这个时间设为0,就代表立即插入到队列,但不是立即执行,仍要等待前面代码执行完毕。所以setTimeout并不能保证执行的时间,是否及时执行取决于javascript 线程拥挤还是空间。
function order(){
console.log(1);
num = 2;
var timer = setTimeout("console.log(num)",0);
console.log(3);
};
// 输出为 1,3,2
7.参考文献
参考一:
JavaScript定时器实现的原理分析
参考二:
BOM系列第一篇之定时器setTimeout和setInterval
参考三:
setTimeout和setInterval从入门到精通
8.更多讨论
如何动态改变定时器的时间间隔?
使用定时器可以实现哪些有趣的功能?
9.提问互动
1.setInterval、setTimeout 中的函数引用,带引号和不带引号有什么区别?
答:带引号的“test()”和不带引号的 test 是一样的,都是表示 test 函数,在一定时间时候调用该函数。而将带引号的方法去掉引号,变成 test(),则在解析到定时器这一行的时候,会发现 test()是函数调用(执行),会先进行函数调用,便将定时器忽略掉了。所以要是带括号的话,必须要加引号。
2.setTimeOut 只能用于单次执行吗?
答:不是的。若想要多次调用,可以让 code 自身再次调用 setTimeOut。demo如下:
function test(){
console.log("咕咕咕")
ggg = setTimeout(test,1000);
};
3.关于 setTimeOut 的this指向哪里?
答:setTimeout方法是挂在window对象下的。超时调用的代码都是在全局作用域中执行的,因此函数中this的值在非严格模式下指向window对象,在严格模式下是undefined。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。