Google Chrome 的 console.log() 打印 DOM 节点不一致

Sip*_*ipo 15 javascript google-chrome google-chrome-devtools console.log

不是Google Chrome console.log() inconsistency with objects and arrays的重复,因为这个问题与对象和数组无关。


这是一个简单的 HTML 页面:

<head>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div></div>
  <div></div>
  <div></div>
  <div></div>

  <script>
    for (const div of document.querySelectorAll("div")) {
      console.log(div);
    }
  </script>
</body>
Run Code Online (Sandbox Code Playgroud)

有时结果会按预期显示:

在此输入图像描述

有时好像我用console.dir()而不是console.log()

在此输入图像描述

很少,我会混合:

在此输入图像描述

当我尝试创建上面所示的最小的、可重现的示例时,我删除了<link>,因为它似乎与问题无关。然而,删除它之后,不一致的情况消失了,所以我恢复了它,并尝试最小化 CSS 本身,直到style.css目前完全为空。因此,不知何故,标签的存在<link>似乎至少与问题有关。

这种行为是否有原因,或者是一个错误?

syd*_*uki 3

这不是一个错误,也不是一个功能,而是更多的权衡。我回答了一个关于“如何”的类似问题,因此很简短。这里讲的是“为什么”,所以需要更多的“学术”解释。它与Chromium DevTools日志记录如何与Blink引擎结合使用
有关,下面是 DOM 节点的简化场景:

console.log(document.querySelector('div'));
Run Code Online (Sandbox Code Playgroud)

Blink V8::console.log -> IPC -> Chromium Process -> IPC -> DevTools front-end fork

也就是说,V8执行console.logBlink 实现的方法,该方法触发 的消息DevTools。该消息的处理方式IPC在 Blink 中主要是异步的。一旦DevTools Console接收到一个Node对象,它必须检查DOM Renderer与它的实际渲染树同步,这样当鼠标悬停在控制台中的节点上时,它Renderer会突出显示浏览器页面中的节点,所以它是:

DevTools inspect -> IPC -> Chromium Process -> IPC -> Blink DOM Render

问题在于,由于正DOM Renderer忙于同步样式加载,在这种特定情况下,渲染阻塞资源link元素,因此它无法及时响应,而不是渲染树表示,控制台回退到它的对象表示,而是这样做仅显示字符串表示形式无论如何都可以检查该节点,这是一个合理的权衡,尽管没有看到它的镜像引用的商品。此外,还可能注意到
其他特性:DevTools Console

  • console调用哪个方法并不重要,因为它们主要是日志级别定义的别名,而不是用于对象检查的特殊处理,因此console.error行为相同。
  • DevTools inspect仅当选项卡处于活动状态或变为活动状态时才会发出Console。因此,虽然在使用活动选项卡执行测试时它可能会显示节点的对象Console表示,但在另一个选项卡上执行测试时,比如说Performance,然后切换到Console我们可以看到这些节点一个接一个地显示为渲染树,因为这样时间DOM Render将可访问。
  • 关于记录对象的一个​​常见误解是,当 JS 运行时改变它们时,它们在控制台中也会发生改变。嗯,他们不是。仅为当前级别树创建Console对象的静态“指纹” 。然后,当手动展开树时,它会根据需要创建更深的树,因此它仅将当前值用于该新树,这可能会产生它改变了 log 的错误印象

我对最初的示例进行了一些修改,使其更像“真实”的应用程序,也揭示了上述行为。此外,为了对渲染引擎施加更大的压力,可以在选项卡中使用x4x6CPU 节流来播放它DevTools Performance

console.log(document.querySelector('div'));
Run Code Online (Sandbox Code Playgroud)

注意:结果console.log必须在此处检查,而DevTools不是在游乐场中检查,因为它只是使用自己的解析器解析参数console.log,与实际行为无关console.log