You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用DOM API时JavaScript为何不遵循常规顺序执行?

为什么DOM对象的console.log输出不符合JS顺序执行预期?

普通对象的正常执行示例

function tellMeWhatsPassed(thing){
   console.log(thing)
}

function createThing(){
   const div = {}
   div.innerHTML = 'original'
   tellMeWhatsPassed(div)
   div.innerHTML = 'updated'
   tellMeWhatsPassed(div)
}

createThing()

// 输出:
// {innerHTML: 'original'}
// {innerHTML: 'updated'}

执行顺序说明

JS会先声明tellMeWhatsPassed和createThing函数,调用createThing()时进入其执行上下文:创建空对象并赋值innerHTML: 'original',调用函数输出该对象;接着修改innerHTML为updated,再次调用函数输出更新后的对象,完全符合逐行顺序执行逻辑。

DOM元素的特殊输出示例

function tellMeWhatsPassed(thing){
   console.log(thing)
}

function createThing(){
   const div = document.createElement('div')
   div.innerHTML = 'original'
   tellMeWhatsPassed(div)
   div.innerHTML = 'updated'
   tellMeWhatsPassed(div)
}

createThing()

// 输出(控制台展开后):
// <div> updated </div>
// <div> updated </div>

原因解析

JS的顺序执行根本没被打破,代码确实是按顺序先打印DOM元素、再修改innerHTML、再打印的。问题出在浏览器控制台对DOM元素的打印机制:

  • 当你用console.log打印DOM元素时,控制台并不会立即生成该元素状态的快照,而是只保存一个指向这个DOM元素的引用。
  • 当你在控制台中点击展开这个DOM元素查看详情时,浏览器才会去读取该元素当前的实时状态——而此时你的代码已经完成了innerHTML的修改,所以两次打印的引用指向的都是已经更新后的DOM元素,看起来就像两次输出都是修改后的值。

而普通对象不存在这个问题,因为console.log打印普通对象时,会默认快照它当前的可枚举属性状态,后续修改不会影响已经打印的快照内容。

内容的提问来源于stack exchange,提问作者OReilly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 06:06:45