调用栈是同步执行的唯一通道,遵循LIFO原则,仅处理同步代码:函数调用时压入执行上下文,返回时立即弹出;异步任务交由Web API处理并进入任务队列,须待调用栈清空后由事件循环按微任务优先、宏任务排队的规则调度。

调用栈是同步执行的唯一通道
调用栈是一个后进先出(LIFO)的结构,它只负责执行同步代码。每当函数被调用,JS 引擎就创建一个执行上下文并压入栈顶;函数返回后,该上下文立即弹出。整个过程不涉及任何异步逻辑——它不会暂停、不会等待、也不会跳过。比如 console.log('a')、add(2, 3) 这类语句,全部在调用栈中顺序完成。
异步任务不进调用栈,而是交给 Web API 处理
当遇到 setTimeout、fetch、addEventListener 等异步操作时,JS 引擎不会把回调直接塞进调用栈。而是:
- 把定时器或请求交由浏览器/Node.js 的 Web API 模块接管
- 当前函数继续执行,调用栈不受影响
- 等 Web API 完成工作(如 0ms 到期、响应返回),再把对应回调放入任务队列
也就是说:调用栈空了,才是事件循环开始干活的前提。
事件循环按优先级取任务:先清微任务,再取宏任务
一旦调用栈清空,事件循环立刻介入,但不是“随便挑一个”来执行。它的规则非常明确:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
立即学习“Java免费学习笔记(深入)”;
- 检查微任务队列(Microtask Queue):如有 Promise.then、MutationObserver 回调,全部连续执行,直到队列为空
- 再检查宏任务队列(Macrotask Queue):只取最先进入的一个(如 setTimeout 回调),压入调用栈执行
- 执行完这个宏任务后,再次清空微任务队列,再取下一个宏任务……如此循环
这个“微任务优先、宏任务排队”的机制,决定了常见输出顺序:同步代码 → 所有 .then → 一个 setTimeout → 下一轮微任务……
为什么不能靠 setTimeout(0) 实现“立刻执行”?
很多人误以为 setTimeout(fn, 0) 能让代码插队到同步任务之后马上运行,其实不然:
- 它仍属于宏任务,必须等当前调用栈清空 + 所有微任务跑完,才轮得到它
- 即便计时器早已到期,它也得在下一轮事件循环中排队等候
- 相比之下,
Promise.resolve().then(fn)会进入微任务队列,总比 setTimeout 先执行
所以真正想“紧接同步代码之后执行”,应选微任务,而不是依赖 setTimeout 的毫秒数。

















