A1. 要素 (核心零件)
- Call Stack (调用栈): 主跑道。所有的 JS 代码(函数)都在这里执行。后进先出 (LIFO)。
- Web APIs (浏览器能力/Node.js的 API): 幕后工人。负责
setTimeout计时、fetch网络请求、DOM事件监听。它们独立于 JS 主线程运行。 - Callback Queue (任务队列): 候车室。异步操作完成后的回调函数(如
onload、then)在这里排队。- 进阶区分: 宏任务 (MacroTask): 比如
setTimeout,setInterval, I/O。 - 进阶区分: 微任务 (MicroTask): 比如
Promise.then,process.nextTick
- 进阶区分: 宏任务 (MacroTask): 比如
A2. 结构 (运行规则) 这是一个无限循环:
- 执行栈: 先把 Stack 里所有的同步代码跑完。(html 当中的
- 执行宏任务: 先执行宏任务队列当中一个任务,并把下一个任务推入宏任务队列当中。
- 检查微任务: 执行完一个宏任务过后,立刻查看微任务队列(VIP 通道)。如果有,全部执行完。
- 渲染更新阶段:
- 检查当前帧是否有渲染需求(如果未到刷新时间或页面完全无变化,则跳过此阶段)。
- Resize/Scroll 事件:处理窗口缩放或滚动。
- 执行 requestAnimationFrame (rAF): 这是开发动画的最佳时机,因为它能确保回调在计算样式和布局之前执行。
- 样式计算 (Recalculate Style):确定每个元素应用哪些 CSS 规则。
- 布局 (Layout/Reflow):计算每个元素在屏幕上的几何位置。
- IntersectionObserver:处理元素可见性变化的回调。
- 绘制 (Paint):构建图层树,提交给合成线程(Compositor Thread)进行栅格化和显示。
- 分层与合成:浏览器将各个图层分别绘制过后,最后由GPU合成在一起
- 浏览器空闲阶段:如果当前帧在完成上述工作后还有剩余时间(小于 16.6ms),且无紧急任务,执行 requestIdleCallback回调
- 循环: 回到第 2 步。
A3. 系统 (涌现功能) 这个系统实现了**“非阻塞 I/O”**。JS 不会因为网络请求慢而卡死界面,它把耗时任务甩给浏览器(Web APIs),自己继续处理用户的点击,等数据回来了再处理数据。
如果切到 Node 语境,可以继续看 Node 包含哪些线程:Node 默认通常是一个进程,由 JS 主线程、底层线程池和宿主能力一起支撑事件循环。
console.log('1. 开始');
setTimeout(() => {
console.log('2. 宏任务 (普通排队)');
}, 0);
Promise.resolve().then(() => {
console.log('3. 微任务 (VIP插队)');
});
console.log('4. 结束');输出顺序: 1 → 4 → 3 → 2 (注意:3 竟然在 2 前面,尽管 2 是先写的)