mutationobserver 回调属于微任务,与 promise 回调同级,均在当前宏任务结束后、下一个宏任务开始前按入队顺序 fifo 执行,因此总早于 settimeout;其回调异步批量触发,不实时响应 dom 变更。

在 JavaScript 的 Event Loop 中,MutationObserver 回调属于微任务(microtask),而 setTimeout/setInterval 属于宏任务(macrotask),这是它们执行顺序差异的根本原因。
微任务队列优先于宏任务队列执行
每当一次宏任务(如脚本执行、事件回调、定时器触发)完成之后,引擎会立即清空当前的微任务队列——按先进先出(FIFO)顺序执行所有已排队的微任务,包括:
- Promise.then/catch/finally 回调
- MutationObserver 的回调
- queueMicrotask() 注册的任务
这个过程发生在「当前宏任务结束」和「下一个宏任务开始」之间,因此 MutationObserver 总是比下一轮宏任务(比如 setTimeout 回调)更早执行。
MutationObserver 不是“实时”响应,而是异步批量执行
MutationObserver 并不会在每次 DOM 变更后立刻同步执行回调,而是将变更记录暂存,等当前 JS 执行栈清空、进入微任务阶段时,统一触发一次回调(并传入所有待处理的变更记录)。这意味着:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 多次 DOM 修改可能只触发一次 observer 回调
- 该回调一定排在当前宏任务之后、下一个宏任务之前
- 即使你在 setTimeout 前注册 observer 并触发 DOM 变更,observer 回调仍会先于 setTimeout 执行
一个典型执行顺序示例
以下代码可验证执行优先级:
console.log(1);
setTimeout(() => console.log(2), 0);
const obs = new MutationObserver(() => console.log(3));
obs.observe(document.body, { childList: true });
document.body.appendChild(document.createElement('div')); // 触发变更
Promise.resolve().then(() => console.log(4));
console.log(5);
输出顺序为:1 → 5 → 3 → 4 → 2。说明:
- 1 和 5 是同步代码,立即执行
- 3(MutationObserver)和 4(Promise)都是微任务,在同步代码结束后依次执行
- 2 是宏任务,排在下一轮事件循环,最后执行
注意:MutationObserver 的优先级不高于 Promise
MutationObserver 和 Promise 回调同属微任务,但具体执行顺序由入队先后决定,不是“Observer 一定比 Promise 先”。例如:
- 先触发 DOM 变更 → observer 入队
- 再 Promise.resolve().then(...) → then 回调入队
- 则 observer 先执行
- 反之,若 Promise 先入队,则它先执行
浏览器规范未强制规定不同微任务类型间的绝对优先级,但实际中各引擎(Chrome/V8、Firefox/SpiderMonkey)都按入队顺序 FIFO 执行所有微任务。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










