JavaScript 是单线程语言,靠事件循环(Event Loop)协调同步与异步任务,实现非阻塞运行。
代码执行时,函数调用被压入**调用栈(Call Stack)**,遵循后进先出原则。同步代码立即执行,栈空则当前任务完成。
例如:console.log("A"); setTimeout(() => console.log("B"), 0); console.log("C"); 会先输出 A、C,B 稍后才出现——因为 setTimeout 的回调不进调用栈,而是交给 Web API 暂存。
事件循环持续监听两个关键队列:
catch/finally、queueMicrotask()、MutationObserver
每次宏任务执行完,事件循环会清空整个微任务队列,再取下一个宏任务——这就是 Promise 回调总比 setTimeout 先执行的原因。
运行以下代码:
console.log(1); setTimeout(() => console.log(2), 0); Promise.resolve().then(() => console.log(3)); console.log(4);
输出为:1 → 4 → 3 → 2。逻辑是:
Node.js 的事件循环有更细的阶段划分(如 timers、pending callbacks、poll、check、close callbacks),process.nextTick() 的优先级甚至高于 Promise 微任务;而浏览器中 Promise 始终是最高等级微任务。实际开发中,应以 微任务 这一基本原则为准,避免跨环境强依赖执行时序。