window
一个 JS 线程,因此只有在每个特定的时刻只有特定的代码能够执行,并且阻塞后续代码。尽管 HTML5 提出了 Web Worker 标准,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制,且不能够操作 DOM。所以,Web Worker 标准并没有改变 JavaScript 单线程的本质。
bar
时,创建了第一个栈帧,栈帧中包含了bar
的参数和局部变量。当bar
调用foo
时,创建第二个栈帧,栈帧中包含了foo
的参数和局部变量,并被压到第一个栈帧之上。当foo
返回时,最上层的栈帧就被弹出(剩下bar
函数的调用帧 )。当bar
返回的时候,栈就空了。后面提到 task queue 和 job queue 都被视为一种 message queue。
此外,在零延迟调用 setTimeout 等函数添加异步任务时,并不是过了给定的时间间隔后就马上执行回调函数。其等待的时间基于队列里正在等待的消息数量。 setTimeout 等本质上是 JS 线程调用了其它线程,其它线程在条件达成时把任务塞入队列。
requestAnimationFrame
,然后将任务添加到动画队列中。
在渲染管道重新渲染屏幕之前,动画队列并不会弹出任何的任务。
当渲染管道准备重新渲染屏幕时,会先执行动画队列中一部分的任务,最后才进行屏幕的渲染。事实上并不止这三个
setImmediate
并解析回调来向检查阶段队列添加任务。由于实现方式的原因,setImmediate(cb)
要优先于setTimeout(cb, 0)
执行cb
。Promise
,每个宏任务完成后,继续运行 Promise
微任务队列。nextTick
队列。nextTick
队列要优先与Promise
微任务队列。setImmediate
和process.nextTick
这两个 API 的实现上。setImmediate(fn): do something on the next tick process.nextTick(fn): do something immediately