setTimeout 原理详解
一句话结论:
setTimeout(fn, 0)也不是“立刻执行”;它只是在计时到期后把回调放进宏任务队列,真正执行要等主线程空闲且排到它。
1. 发生了什么(简化版)
- 调用
setTimeout:浏览器把fn交给计时器模块登记(不在 JS 栈里等待) - 到期:把
fn放入对应的宏任务队列(task queue) - 事件循环取任务:当调用栈清空,才有机会取出
fn执行
2. 为什么不准时
- 主线程忙:同步代码/渲染/微任务太多都会推迟执行
- 计时器精度与钳制(clamp):浏览器会对极短延时做最小值限制(常见 4ms 等策略,具体与嵌套层级/后台标签页有关)
3. 与 Promise 的常见顺序
setTimeout(() => console.log("timeout"), 0);
Promise.resolve().then(() => console.log("microtask"));
// 常见:microtask 先于 timeout