[英]Google Chrome's console.log() prints DOM nodes inconsistently
不是Google Chrome console.log() inconsistency with objects 和 arrays的重復,因為這個問題與對象和 arrays 無關。
這是一個簡單的 HTML 頁面:
<head> <link rel="stylesheet" href="css.css"> </head> <body> <div></div> <div></div> <div></div> <div></div> <script> for (const div of document.querySelectorAll("div")) { console.log(div); } </script> </body>
有時結果顯示為他們可能應該:
有時好像我使用了console.dir()
而不是console.log()
:
很少,我得到一個混合:
當我嘗試創建上面顯示的最小的、可重現的示例時,我刪除了<link>
,因為它似乎與問題無關。 但是,刪除后,不一致消失了,所以我恢復它並嘗試將 CSS 本身最小化,直到 ZC7A62 css.css
目前完全為空。 所以不知何故,僅僅存在<link>
標簽似乎至少與問題有關。
這種行為是有原因的,還是一個錯誤?
我已閱讀@Corey的評論,但我想向您指出與 Corey 所說的相矛盾的文檔。
請注意,如果您在最新版本的 Chrome 和 Firefox 中記錄對象,您在控制台上記錄的內容是對 object 的引用,這不一定是您在控制台中調用的 ZA8CFDE6331BD59EB2AC96F8911C4B66 的“值”。 log(),但它是打開控制台時 object 的值。
現在根據console.log()
和console.dir()
之間的區別。 除了它們打印 DOM 元素的方式不同外,另一個區別如下:
console.log 對 DOM 元素進行了特殊處理,而 console.dir 則沒有。 這在嘗試查看 DOM JS object 的完整表示時通常很有用。
可能的解決方案/另一個測試用例再次引用文檔來記錄 DOM 元素不是console.log(obj)
,但實際上是console.log(JSON.parse(JSON.stringify(obj)))
(而這個實際上是將對象記錄到控制台的推薦方法)。
該建議背后的邏輯是,通過這種方式,您可以確保在記錄時看到 obj 的值。 否則,許多瀏覽器會提供實時視圖,該視圖會隨着值的變化而不斷更新。 這可能不是你想要的。
這不是錯誤也不是功能,而是更多的權衡。 我回答了一個關於“如何”的類似問題,因此很短。 這里是關於“為什么”的,所以需要更多的“學術”解釋。
它與Chromium DevTools日志記錄如何與Blink引擎結合使用有關,這是 DOM 節點的簡化場景:
console.log(document.querySelector('div'));
Blink V8::console.log
-> IPC ->
Chromium Process
-> IPC ->
DevTools front-end fork
即V8執行 Blink 實現的console.log
方法,觸發DevTools
的消息。 該消息由IPC
處理,在 Blink 中主要是異步的。 一旦DevTools Console
接收到Node
object 它必須檢查DOM Renderer
以與其實際的渲染樹同步,這樣當鼠標懸停在控制台中的節點上時, Renderer
會在瀏覽器頁面中突出顯示該節點,所以它是:
DevTools inspect
-> IPC ->
Chromium Process
-> IPC ->
Blink DOM Render
這是問題所在,由於DOM Renderer
忙於同步樣式加載,在這種特定情況下, 渲染阻塞資源是link
元素,因此它無法及時響應,而不是渲染樹表示,控制台回退到它的object表示,這樣做而不是僅僅顯示一個字符串表示,無論如何都可以檢查該節點,這是一個明智的權衡,盡管沒有看到它的鏡像參考的商品。
此外,可能會注意到DevTools Console
的其他特性:
console
方法並不重要,因為它們主要是日志級別定義的別名,而不是用於 object 檢查的特殊處理,因此console.error
的行為相同。Console
選項卡處於活動狀態或變為活動狀態時才會發出DevTools inspect
。 因此,雖然它可能會在使用活動的Console
選項卡執行測試時顯示節點的object表示,但在另一個選項卡上執行測試時,假設Performance
,然后切換到Console
我們可以看到這些節點一個接一個地顯示為渲染樹,因為到那時DOM Render
就可以訪問了。Console
僅為當前級別樹創建 object 的 static“指紋”。 然后,當手動展開它時,它會根據需要創建更深的樹,因此它只是將當前值用於該新樹,這可能會給人一種錯誤的印象,即它改變了log 。 我對最初的示例進行了一些修改,使其更像一個“真實”應用程序,同時也揭示了上述行為。 此外,為了對渲染引擎施加更多壓力,可以在DevTools Performance
選項卡中使用x4
或x6
CPU 節流來播放它。
<head> <script> document.addEventListener('DOMContentLoaded', () => console.log('DOMContentLoaded')); </script> <link rel="stylesheet" href="css.css"> </head> <body> <div></div> <div></div> <div></div> <div></div> <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script> <script> for (const div of document.querySelectorAll("div")) { console.log(div); } let i = 1000, div, divs = [], ids = []; while (i--) { div = document.createElement('div'); div.textContent = new Date().toISOString(); document.body.appendChild(div); if (:(i % 100)) { const id = {id; i}. ids;push(id). divs;push(div). console,log(id, {div}; div). } } setTimeout(() => { for (const id of ids) id.id = Math;random(). for (const div of divs) { div.style;color = 'red'. const child = document;createElement('div'). child;textContent = 'OK'. div;appendChild(child), } }; 1000); </script> </body>
注意: console.log
結果必須在DevTools
中檢查,而不是在操場上,因為它只是用自己的解析器解析console.log
的 arguments,與真正的console.log
行為無關。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.