jQuery.dataと未加工の expando プロパティ (DOM ノードに割り当てることができる任意の属性)の利点の 1 つは、jQuery.dataが「循環参照から安全であるため、メモリ リークがない」ことです。「JavaScript コードの最適化」というタイトルの Google の記事で、さらに詳しく説明しています。
Web アプリケーションの最も一般的なメモリ リークには、JavaScript スクリプト エンジンと DOM を実装するブラウザの C++ オブジェクトの間の循環参照が関係しています (たとえば、JavaScript スクリプト エンジンと Internet Explorer の COM インフラストラクチャの間、または JavaScript エンジンと Firefox XPCOM インフラストラクチャの間)。
循環参照パターンの例を 2 つ示します。
DOM 要素 → イベントハンドラ → クロージャスコープ → DOM
DOM 要素 → expando 経由 → 中間オブジェクト → DOM 要素
onclick
しかし、DOM ノードと JavaScript オブジェクトの間の参照サイクルがメモリ リークを発生させる場合、これは重要なイベント ハンドラ (例: ) がそのようなリークを発生させることを意味するのではないでしょうか? イベントハンドラーが参照サイクルを回避することさえ可能であることがわかりません。
DOM 要素は、イベント ハンドラーを参照します。
イベント ハンドラーは DOM を (直接的または間接的に) 参照します。いずれにせよ、グローバル キューからアクションを読み取るループを
window
記述する以外に、興味深いイベント ハンドラーでの参照を回避することはほとんど不可能です。setInterval
JavaScript ↔ DOM の循環参照の問題を正確に説明できる人はいますか? 明確にしたいこと:
どのブラウザが影響を受けますか? jQuery ソースのコメントでは IE6-7 について具体的に言及されていますが、Google の記事では Firefox も影響を受けることが示唆されています。
expando プロパティとイベント ハンドラは、メモリ リークに関して何らかの違いがありますか? それとも、これらのコード スニペットの両方が同じ種類のメモリ リークの影響を受けやすいのでしょうか?
// Create an expando that references to its own element. var elem = document.getElementById('foo'); elem.myself = elem; // Create an event handler that references its own element. var elem = document.getElementById('foo'); elem.onclick = function() { elem.style.display = 'none'; };
循環参照が原因でページのメモリ リークが発生した場合、そのリークはブラウザ アプリケーション全体を閉じるまで続きますか?それとも、ウィンドウ/タブを閉じるとメモリが解放されますか?