現在、Trevor BurnhamによるAsync Javascriptを読んでいます。これはこれまでのところ素晴らしい本です。
彼はこのスニペットとconsole.logがSafariとChromeコンソールで「非同期」であることについて話します。残念ながら、これを複製することはできません。これがコードです:
var obj = {};
console.log(obj);
obj.foo = 'bar';
// my outcome: Object{}; 'bar';
// The book outcome: {foo:bar};
これが非同期の場合、私は結果が本の結果になると予想します。console.log()は、すべてのコードが実行されるまでイベントキューに入れられ、その後実行され、barプロパティを持ちます。
同期して動いているのに見えます。
このコードを間違って実行していますか?console.logは実際には非同期ですか?
console.log
は標準化されていないため、動作はかなり未定義であり、開発者ツールのリリースごとに簡単に変更できます。私の回答がすぐにわかるように、あなたの本は古くなっている可能性があります。
私たちのコードでconsole.log
は、非同期であるかどうかに関係なく、コールバックなどは提供されていません。渡した値は常に参照され、関数を呼び出すときに計算されます。
そのとき何が起こるのか本当にわかりません(Firebug、Chrome Devtools、Opera Dragonflyはすべてオープンソースなので、できます)。コンソールはログされた値をどこかに保存する必要があり、画面に表示します。レンダリングは確実に非同期で行われ(レート制限の更新に抑制されます)、コンソールでログに記録されたオブジェクトとの今後の相互作用(オブジェクトプロパティの拡張など)も同様です。
そのため、コンソールは、ログに記録した可変オブジェクトを複製(シリアル化)するか、それらへの参照を保存します。最初のものは、ディープ/ラージオブジェクトではうまく機能しません。また、少なくともコンソールの最初のレンダリングでは、おそらくオブジェクトの「現在の」状態、つまりオブジェクトがログに記録されたときの状態が表示されますObject {}
。
ただし、オブジェクトを展開してそのプロパティをさらに検査すると、コンソールにはオブジェクトとそのプロパティへの参照のみが格納され、それらを表示すると現在の(すでに変更された)状態が表示される可能性があります。をクリックすると+
、bar
例のプロパティが表示されます。
バグレポートに投稿された「修正」を説明するスクリーンショットを次に示します。
そのため、一部の値は、ログに記録されてからかなり後に参照される可能性があり、これらの評価はかなり遅延されます(「必要な場合」)。この不一致の最も有名な例は、ChromeのJavaScriptコンソールが配列の評価について怠惰なのかという質問で扱われています。
回避策は、たとえばを実行するなどして、オブジェクトのシリアル化されたスナップショットを常にログに記録するようにすることconsole.log(JSON.stringify(obj))
です。ただし、これは非円形でかなり小さいオブジェクトに対してのみ機能します。参照してくださいどのように私はSafariではconsole.logのデフォルトの動作を変更することができますか?。
より良い解決策は、デバッグにブレークポイントを使用することです。この場合、実行は完全に停止し、各ポイントで現在の値を検査できます。シリアル化可能なデータと不変のデータでのみログを使用します。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加