setTimeOut设置为0,会在队列最后添加一个事件,要等待其他任务事件处理完成才会处理。
js EventLoop详见EventLoop
延迟的毫秒数 (一秒等于 1000 毫秒),函数的调用会在该延迟之后发生。如果省略该参数,delay 取默认值 0,意味着“马上”执行,或者尽快执行。不管是哪种情况,实际的延迟时间可能会比期待的 (delay 毫秒数) 值长,
setTimeout的最小延迟时间问题:
有很多因素会导致 setTimeout 的回调函数执行比设定的预期值更久,一般来说最小延时 >=4ms。
具体原因:
1、在浏览器中,setTimeout/setInterval的每调用一次定时器的最小间隔是 4ms,这通常是由于函数嵌套导致(嵌套层级达到一定深度),或者是由于已经执行的 setInterval 的回调函数阻塞导致的。例如:
function cb() { f(); setTimeout(cb, 0); }
setTimeout(cb, 0);
setInterval(f, 0);
在 Chrome 和 Firefox 中, 定时器的第 5 次调用被阻塞了;在 Safari 是在第 6 次;Edge 是在第 3 次。Gecko 从这个版本 version 56开始对 setInterval() 开始采用这样的机制
一直以来,不同浏览器中出现这种最小延迟的情况有所不同(例如 Firefox)- 从其他地方调用了 setInterval( ),或者在嵌套函数调用 setTimeout( ) 时(嵌套级别达到特定深度时),都会出现超时延迟。
2、超时延迟
除了"最小延时"之外,定时器仍然有可能因为当前页面(或者操作系统/浏览器本身)被其他任务占用导致延时。 需要被强调是, 直到调用 setTimeout()的主线程执行完其他任务之后,回调函数和代码段才能被执行。例如
function foo() {
console.log('foo has been called');
}
setTimeout(foo, 0);
console.log('After setTimeout');
会在控制台输出:
After setTimeout
foo has been called
出现这个结果的原因是,尽管setTimeout 以 0ms 的延迟来调用函数,但这个任务已经被放入了队列中并且等待下一次执行;并不是立即执行;队列中的等待函数被调用之前,当前代码必须全部运行完毕,因此这里运行结果并非预想的那样