JavaScript定时器
一、什么是定时器
JavaScript提供了一些原生的方法来实现延时去执行某一段代码,下面简单介绍一下:
setTimeout
:设置一个定时器,在定时器到期后执行一次函数或代码段,
1 | var timeoutId = window.setTimeout(func|code, delay); |
- timeoutId: 定时器ID
- func: 延迟后执行的函数
- code: 延迟后执行的代码字符串,不推荐使用原理类似eval()
- delay: 延迟的时间(单位:毫秒),默认值为0
setInterval
: 以固定的时间间隔重复调用一个函数或者代码段·
1 | var intervalId = window.setInterval(func|code, delay); |
- intervalId: 重复操作的ID
- func: 延迟调用的函数
- code: 代码段
- delay: 延迟时间,没有默认值
另外,还有两种不常见的定时器:setImmediate
, requestAnimationFrame
。
二、定时器的工作原理以及不定时的原理
JavaScript是一个单线程的解释器,因此一定时间内只能执行一段代码。为了要控制执行的代码,就有一个JavaScript任务队列。这些任务会按照它们添加到队列的顺序执行。
setTimeout()
的第二个参数告诉JavaScript再过多长时间把当前任务添加到队列中。如果队列是空的,那么添加的代码会立即执行;如果队列不是空的,那么它就要等前面的代码执行完了以后再执行。
【注意】:
- 首先,JavaScript是以单线程的方式运行的。JavaScript的主要用途是与用户互动,以及操作DOM。若以多线程的方式,则可能出现冲突。假设有两个线程同时操作一个DOM元素,线程1要求浏览器删除DOM,而线程2却要求修改DOM样式,这时浏览器就无法决定采用哪个线程的操作。(但是JavaScript有个基于“Event Loop”并发的模型。<此处不讨论。。>)
- js既然是单线程的,也就意味着所有任务需要排队。所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)
- 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务,形成了一个执行栈
- 异步任务指的是,不进入主线程,而进入”任务队列”(task queue)的任务。”任务队列”是一个事件的队列(可以当作消息的队列来理解)。IO设备完成一项任务or异步任务有了运行结果,就在”任务队列”中添加一个事件,表示相关的操作可以进入”执行栈”,就等着执行栈调用了。
- 因为
setTimeout
,setInterval
是异步任务,调用之后不会直接进入执行栈,而是进入任务队列,所以只有等到当前执行栈没有其他操作,它们才会进入执行栈中执行, 以上就是为什么定时器不总是定时的原因了。 - 如果
delay
时间周期设为0,相当于一个插队操作
三、实例
例1:
1 | var a = true; |
console.log(a)
永远不会执行,因为JavaScript是单线程的,且定时器的回调将在等待当前正在执行的任务完成后才执行,而while(a){}
直接进入了死循环,一直占用线程,不会给回调函数执行机会。
例2:
1 | for (var i = 0; i < 5; i++) { |
代码会输出5 5 5 5 5
。当i = 0
时,生成一个定时器,将回调函数插入到事件队列中,等待当前队列中无任务执行时立即执行,而此时for
循环正在执行,所以回调被搁置。当for循环执行完之后,队列中存在5个回调函数,它们都将执行console.log(i)
的操作,因为当前JS代码中并没有使用块级作用域,所以i
的值在for
循环结束后一直为5.
例3:
1 | var obj = { |
这个问题涉及到了this
的指向问题,由setTimeout()
调用的代码运行在与与所在函数完全分离的执行环境上。这会导致这些代码中包含的this
关键字会指向window
(或全局)对象,window
对象中并不存在shout
方法,所以就会报错。
可以这样修改:
1 | var obj = { |
四、注意事项
- 我们可以使用
clearTimeout()
和clearInterval()
方法来取消定时器 - 对于
setTimeout(f, 0)
指定时间为0,并不是说回调函数f
会马上执行,而是会在下一轮事件循环一开始就执行。 - 在使用超时调用时,没必要跟踪超时调用ID,因为每次执行代码之后,如果不再设置另一次超时调用,调用就会自行停止。
- 最好不要使用间歇调用
五、参考
《JavaScript高级程序设计》第三版
MDN