John Resig在How JavaScript Timers Work一文中,对setTimeout和setInterval的分析很精辟:

总结如下:

  • JavaScript engines only have a single thread, forcing asynchronous events to queue waiting for execution.
  • setTimeout and setInterval are fundamentally different in how they execute asynchronous code.
  • If a timer is blocked from immediately executing it will be delayed until the next possible point of execution (which will be longer than the desired delay).
  • Intervals may execute back-to-back with no delay if they take long enough to execute (longer than the specified delay).

我的心得:

  1. 无论是setTimeout还是setInterval,触发时,如果当前进程不为空,都得去排队等待执行,这一点上是无差异的。
  2. 区别是,setTimeout只需排一次队,setInterval则需要按照预设的间隔时间,每到时间点都去排一下。
  3. setInterval去排队时,如果发现自己还在队列中未执行,则会被drop掉。也就是说,同一个inerval,在队列里只会有一个。
  4. 因为队列机制,无论是setTimeout还是setInterval,第一次触发时的时间,只会等于大于预设时间,不可能小于。
  5. 对于setInterval来说,如果执行时间大于预设间隔时间,很可能导致连续执行,中间没有时间间隔,这是很糟糕的,很可能会耗费大量cpu.

因此,对于动画来说,如果单帧的执行时间大于间隔时间,用setTimeout比用setInterval更保险。John Resig在回复中也表明了这个观点:

It really depends on the situation – and how the timers are actually being used. setInterval will, most likely, get you more ‘frames’ in the animation but will certainly tax your processor more. A lot of frameworks end up using setTimeout since it degrades more gracefully on slower computers.

一个简单的测试页面:timer_test.html(请在Chrome下运行,注意那些零值或接近零的值,setInterval没有interval了!)

因此,在这种情况下,采用setTimeout更保险:

setTimeout(function(){
    /* Some long block of code... */
    setTimeout(arguments.callee, 10);
  }, 10);

当然,大部分情况下,单帧执行时间都小于预设的间隔时间,上面分析的差异,是感觉不大出来的。