簡體   English   中英

谷歌瀏覽器的 console.log() 打印 DOM 節點不一致

[英]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就可以訪問了。
  • 關於記錄對象的一個常見神話是,當它們被 JS 運行時變異時,它們會在控制台中發生變異。 好吧,他們不是。 Console僅為當前級別樹創建 object 的 static“指紋”。 然后,當手動展開它時,它會根據需要創建更深的樹,因此它只是將當前值用於該新樹,這可能會給人一種錯誤的印象,即它改變了log

我對最初的示例進行了一些修改,使其更像一個“真實”應用程序,同時也揭示了上述行為。 此外,為了對渲染引擎施加更多壓力,可以在DevTools Performance選項卡中使用x4x6 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM