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