同步与异步的本质区别在于是否阻塞主线程:同步任务顺序执行、立即返回结果,前一个未完成则后一个必须等待;异步任务由宿主环境其他线程处理,主线程发起后立即继续执行,结果通过事件循环从任务队列中回调。

同步与异步的本质区别,不在于“谁快谁慢”,而在于任务是否阻塞主线程的后续执行。JavaScript 是单线程语言,所有代码都在一个主线程上运行——这决定了它无法真正“同时”做多件事,但通过事件循环机制,它能高效协调同步与异步任务,避免卡顿。
同步:顺序执行,严格等待
同步任务直接进入调用栈,逐行执行,前一个没结束,后一个就只能等着。比如计算、赋值、DOM 读取等操作,结果立刻可得。
- 代码写在哪,就在哪执行,顺序和逻辑完全一致
- 一旦遇到耗时操作(如大数组排序、深递归),整个页面会卡住,用户无法交互
- 没有回调、不依赖队列,执行完就出栈,简单但脆弱
异步:不占主线程,靠队列调度
异步任务本身不运行在主线程上,而是交由浏览器或 Node.js 的其他线程(如网络线程、定时器线程)处理。主线程只负责发起和收尾——这就是“非阻塞”的关键。
- 发起后立即返回,主线程继续跑后续同步代码
- 完成结果被推入任务队列(宏任务或微任务),等调用栈空了才被事件循环取出执行
- 常见例子:fetch、setTimeout、addEventListener、Promise.then
事件循环:单线程运转的节拍器
事件循环不是额外加的功能,而是 JavaScript 在单线程约束下“假装并发”的核心设计。它持续循环三个动作:执行同步代码 → 清空微任务队列 → 取一个宏任务执行 → 再清空微任务……如此往复。
- 微任务(如 Promise 回调)总比宏任务(如 setTimeout 回调)优先执行
- 每次宏任务执行完,都会检查并执行所有已就绪的微任务,再进入下一个宏任务
- 这个机制让异步逻辑既可控又可预测,是理解 async/await 行为的基础
别混淆:异步 ≠ 多线程
JavaScript 引擎线程始终是单线程的。所谓“异步能力”,其实是宿主环境(浏览器或 Node.js)提供的多线程支持——JS 只管发指令、收回调。比如发一个请求,是网络线程在干活;计时是定时器线程在数秒;JS 主线程全程只做两件事:安排任务、处理结果。
- Web Worker 虽能开新线程,但不能操作 DOM,也不改变 JS 单线程本质
- 真正决定是否异步的,是任务类型和 API 设计,不是你写了 await 或 callback
- 判断一句代码是否异步,看它会不会把控制权交还给主线程后再回来











