console.log() 非同步還是同步?
P粉248602298
P粉248602298 2023-08-27 22:31:53
0
2
516
<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>
P粉248602298
P粉248602298

全部回覆(2)
P粉930534280

這不是問題的真正答案,但對於偶然發現這篇文章的人來說可能會很方便,而且評論太長了:

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粉141925181

console.log 沒有標準化,因此行為相當未定義,並且可以在開發人員工具的不同版本之間輕鬆更改。你的書可能已經過時了,我的答案也可能很快就會過時。

對於我們的程式碼來說,console.log 是否非同步沒有任何區別,它不提供任何類型的回調等;並且您傳遞的值始終在您呼叫該函數時被引用和計算。

我們真的不知道接下來會發生什麼(好吧,我們可以,因為 Firebug、Chrome Devtools 和 Opera Dragonfly 都是開源的)。控制台需要將記錄的值儲存在某處,並將它們顯示在螢幕上。渲染肯定會非同步發生(受到速率限制更新的限制),未來與控制台中記錄的物件的交互也會發生(例如擴展物件屬性)。

因此控制台可能會克隆(序列化)您記錄的可變對象,或者它將儲存對它們的引用。第一個不適用於深/大物體。此外,至少控制台中的初始渲染可能會顯示物件的「目前」狀態,即記錄時的狀態 - 在您的範例中您會看到 Object {}

但是,當您展開物件以進一步檢查其屬性時,控制台可能只儲存對物件及其屬性的引用,現在顯示它們將顯示其目前(已變異)狀態。如果按一下 ,您應該可以在範例中看到 bar 屬性。

這是發佈在錯誤報告中的螢幕截圖解釋他們的「修復」:

因此,某些值可能會在記錄後很久才被引用,並且對這些值的評估相當(「在需要時」)。這種差異最著名的例子是在問題Is Chrome's JavaScript console中處理的懶得評估陣列?

解決方法是確保始終記錄物件的序列化快照,例如透過執行console.log(JSON.stringify(obj))。不過,這僅適用於非圓形和相當小的物體。另請參閱如何更改 Safari 中 console.log 的預設行為?

更好的解決方案是使用斷點進行偵錯,其中執行完全停止,您可以檢查每個點的當前值。僅對可序列化和不可變的資料使用日誌記錄。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板