P粉9305342802023-08-28 22:01:29
這不是問題的真正答案,但對於偶然發現這篇文章的人來說可能會很方便,而且評論太長了:
window.console.logSync = (...args) => { try { args = args.map((arg) => JSON.parse(JSON.stringify(arg))); console.log(...args); } catch (error) { console.log('Error trying to console.logSync()', ...args); } };
這將建立 console.log
的偽同步版本,但具有與接受的答案中提到的相同的警告。
由於目前看來大多數瀏覽器的 console.log
都以某種方式異步,因此您可能希望在某些情況下使用這樣的函數。
P粉1419251812023-08-28 15:47:19
console.log
沒有標準化,因此行為相當未定義,並且可以在開發人員工具的不同版本之間輕鬆更改。你的書可能已經過時了,我的答案也可能很快就會過時。
對於我們的程式碼來說,console.log 是否非同步沒有任何區別,它不提供任何類型的回調等;並且您傳遞的值始終在您呼叫該函數時被引用和計算。
我們真的不知道接下來會發生什麼(好吧,我們可以,因為 Firebug、Chrome Devtools 和 Opera Dragonfly 都是開源的)。控制台需要將記錄的值儲存在某處,並將它們顯示在螢幕上。渲染肯定會非同步發生(受到速率限制更新的限制),未來與控制台中記錄的物件的交互也會發生(例如擴展物件屬性)。
因此控制台可能會克隆(序列化)您記錄的可變對象,或者它將儲存對它們的引用。第一個不適用於深/大物體。此外,至少控制台中的初始渲染可能會顯示物件的「目前」狀態,即記錄時的狀態 - 在您的範例中您會看到 Object {}
。
但是,當您展開物件以進一步檢查其屬性時,控制台可能只儲存對物件及其屬性的引用,現在顯示它們將顯示其目前(已變異)狀態。如果按一下
,您應該可以在範例中看到 bar
屬性。
這是發佈在錯誤報告中的螢幕截圖解釋他們的「修復」:
因此,某些值可能會在記錄後很久才被引用,並且對這些值的評估相當懶(「在需要時」)。這種差異最著名的例子是在問題Is Chrome's JavaScript console中處理的懶得評估陣列?
解決方法是確保始終記錄物件的序列化快照,例如透過執行console.log(JSON.stringify(obj))。不過,這僅適用於非圓形和相當小的物體。另請參閱如何更改 Safari 中 console.log 的預設行為? 。
更好的解決方案是使用斷點進行偵錯,其中執行完全停止,您可以檢查每個點的當前值。僅對可序列化和不可變的資料使用日誌記錄。