1. ホーム
  2. javascript

[解決済み] console.log() async or sync?

2022-10-13 05:51:53

質問

現在読んでいる本 非同期ジャバスクリプト Trevor Burnham著を読んでいます。 これまでのところ、これは素晴らしい本です。

彼は、このスニペットと console.log が Safari と Chrome のコンソールで「非同期」であることについて話しています。残念ながら、私はこれを再現することができません。以下はそのコードです。

var obj = {}; 
console.log(obj); 
obj.foo = 'bar';
// my outcome: Object{}; 'bar';
// The book outcome: {foo:bar};

これが非同期だったら、booksの結果になると予想されます。 console.log()はすべてのコードが実行されるまでイベントキューに入れられ、その後実行され、barプロパティを持つことになるでしょう。

同期的に実行されているように見えますが。

私はこのコードを間違って実行しているのでしょうか?console.logは実際には非同期なのでしょうか?

どのように解決するのですか?

console.log は標準化されていないので、動作はむしろ不定であり、開発者ツールのリリースごとに簡単に変更することができます。あなたの本は古くなっているでしょうし、私の回答もすぐにそうなるかもしれません。

私たちのコードでは console.log が非同期かどうかに違いはなく、コールバックなども提供しません。そして、渡した値は常に関数を呼び出した時点で参照され計算されます。

私たちは、そのとき何が起こるかを実際に知りません (OK、Firebug、Chrome Devtools、および Opera Dragonfly はすべてオープン ソースであるため、私たちは知ることができました)。コンソールはログに記録された値をどこかに保存する必要があり、画面にそれらを表示します。レンダリングは確実に非同期で行われ (更新を制限するためにスロットルされます)、コンソールでログに記録されたオブジェクトとの将来のインタラクション (オブジェクト プロパティの拡張など) と同様に行われます。

したがって、コンソールは、ログに記録された変更可能なオブジェクトをクローン (シリアライズ) するか、それらへの参照を保存します。最初のものは、深い/大きいオブジェクトではうまく機能しません。また、少なくともコンソールの最初のレンダリングは、オブジェクトの "current"状態、つまり、ログに記録されたときの状態を表示するでしょう - あなたの例では Object {} .

しかし、オブジェクトを展開してそのプロパティをさらに調べる場合、コンソールにはオブジェクトとそのプロパティへの参照しか保存されていない可能性があり、今それらを表示すると、現在の(すでに変異した)状態が表示されてしまいます。もし + をクリックすると bar プロパティが表示されているはずです。

に投稿されたスクリーンショットです。 バグレポート に投稿されたスクリーンショットです。

そのため、いくつかの値はログに記録された後もずっと参照される可能性があり、これらの評価はむしろ 怠慢 ("必要なときに")です。この不一致の最も有名な例は、質問で扱われます。 Chrome の JavaScript コンソールは配列の評価に関して遅延していますか?

回避策としては、オブジェクトのシリアル化されたスナップショットを常に記録するようにすることです。 console.log(JSON.stringify(obj)) . これは、円形でない、かなり小さなオブジェクトにのみ有効です。また Safariのconsole.logのデフォルトの動作を変更するにはどうすればよいですか? .

より良い解決策は、デバッグのためにブレークポイントを使うことです。そこでは実行が完全に停止し、各ポイントでの現在の値を検査することができます。ロギングは直列化可能で不変なデータのみに使用します。