JS 单线程、事件循环、微任务、宏任务 一次性讲透
这是 JS 最核心、面试必问、开发必懂的底层原理!我用最通俗的大白话 + 流程图 + 代码示例,让你彻底吃透,再也不晕。
一、先搞懂:JS 为什么是【单线程】?
一句话:
JS 是单线程的——同一时间只能做一件事!
为什么要设计成单线程?
因为 JS 主要运行在浏览器里,负责操作 DOM。
如果是多线程:
- 线程 A 要修改 DOM
- 线程 B 要删除 DOM
浏览器就懵了,不知道听谁的。
所以 JS 从诞生就是单线程,这是它的灵魂,也是一切异步逻辑的根源。
二、单线程遇到的问题:阻塞!
单线程意味着:任务必须排队,一个做完才能做下一个。
如果有个任务很慢(比如定时器、网络请求、读取文件),后面所有代码都会卡住不动,页面就会卡死。
为了解决这个问题,JS 设计了 同步任务 + 异步任务 + 事件循环(Event Loop)。
三、核心概念:同步 vs 异步
1. 同步任务(Synchronous)
- 在主线程排队执行
- 必须等上一个完成,下一个才开始
- 会阻塞代码
console.log(1);
console.log(2); // 必须等1执行完才运行
2. 异步任务(Asynchronous)
- 不进入主线程,先进入 任务队列
- 等主线程空闲了,才会拿过来执行
- 不会阻塞代码(定时器、ajax、点击事件等)
setTimeout(() => {
console.log("我是异步"); // 最后执行
}, 0);
console.log("我是同步"); // 先执行
四、最重要:事件循环(Event Loop)——JS 的执行规则
事件循环就是 JS 执行代码的死循环流程,是异步的底层机制。
一句话总结执行顺序:
先执行所有同步代码 → 再执行所有微任务 → 最后执行宏任务 → 循环往复
完整流程(背下来就无敌):
- 执行主线程的同步代码(调用栈)
- 同步代码执行完,栈空了
- 清空所有微任务队列(全部执行完)
- 去宏任务队列取一个宏任务执行
- 执行完,再次清空所有微任务
- 渲染页面
- 回到第4步,循环……
五、终极难点:微任务 vs 宏任务
1. 宏任务(Macrotask)
- 队列每次只执行一个
- 由宿主环境(浏览器/Node)提供
- 执行慢,优先级低
常见宏任务:
setTimeout/setInterval- 浏览器
I/O操作(ajax、点击事件) script标签整体代码- UI 渲染
2. 微任务(Microtask)
- 队列一次性全部清空
- 由 JS 引擎自身提供
- 执行快,优先级远高于宏任务
常见微任务:
Promise.then / catch / finallyprocess.nextTick(Node 独有)MutationObserver(浏览器独有)queueMicrotask()
六、一句话口诀(面试必背)
同步先执行,微任务次之,宏任务最后!
同一轮循环:所有微任务 > 一个宏任务
七、最经典考题(测一测你懂了没)
看代码,说出输出顺序:
console.log('1 同步');
setTimeout(() => {
console.log('2 宏任务');
}, 0);
Promise.resolve()
.then(() => {
console.log('3 微任务');
});
console.log('4 同步');
正确输出:
1 同步
4 同步
3 微任务
2 宏任务
执行步骤解析:
- 先执行同步:1、4
- 同步完,清空微任务:3
- 最后执行宏任务:2
八、升级版考题(嵌套)
console.log('1');
setTimeout(() => {
console.log('2');
Promise.resolve().then(() => {
console.log('3');
});
}, 0);
Promise.resolve().then(() => {
console.log('4');
setTimeout(() => {
console.log('5');
}, 0);
});
console.log('6');
正确输出:
1
6
4
2
3
5
执行逻辑:
- 同步:1、6
- 微任务:4(里面的宏任务5进入队列)
- 第一个宏任务:2
- 宏任务2里的微任务:3
- 下一个宏任务:5
九、终极总结
执行优先级
同步代码 > 微任务(全部) > 宏任务(一个)
分类速记
- 宏任务:定时器、ajax、点击事件、script
- 微任务:Promise.then、catch、finally、queueMicrotask
核心一句话
JS 是单线程,事件循环来调度,微任务永远比宏任务先执行!
总结
- 单线程:同一时间只做一件事
- 事件循环:JS 的执行调度机制
- 执行顺序:同步 → 微任务 → 宏任务
- 微任务:一次性清空,优先级极高
- 宏任务:每次只执行一个