10

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';
    };
    
  • 循環参照が原因でページのメモリ リークが発生した場合、そのリークはブラウザ アプリケーション全体を閉じるまで続きますか?それとも、ウィンドウ/タブを閉じるとメモリが解放されますか?

4

1 に答える 1

5

これらのリンクのすべてのコンテンツを再現する価値はおそらくないので、他の Google 検索ヒットを読んで確認することをお勧めします。

JavaScript、循環参照、メモリ リーク

JavaScript でメモリ リークが発生する原因を知っていますか?

http://www.ibm.com/developerworks/web/library/wa-memleak/

http://www.ibm.com/developerworks/web/library/wa-sieve/index.html?ca=drs-

http://code.google.com/p/google-web-toolkit/wiki/UnderstandingMemoryLeaks

最悪のメモリ リークは IE6 で発生し、リークは永続的です (影響を受ける Web ページを離れた後でも)。他のリークは通常、その特定のページにいる間だけであり、ページを離れるとクリーンアップされます.

実際には、ブラウザは循環参照を処理できるはずです。DOM 要素がまだ JavaScript 要素によって参照されている場合でも、JavaScript 要素自体が存在するのは、DOM 要素がまだ生きていて、DOM 要素への真の外部参照が残っていないためであることを確認できるはずです。 . 古いバージョンの IE が苦手だったのは、この認識です。したがって、イベント ハンドラーを含むコード参照では、ガベージ コレクターは、JavaScript の DOM 要素に残された唯一の参照が、DOM 要素とそのイベント ハンドラーが削除されたときにそれ自体がなくなる参照であることを認識できるほどスマートである必要があります。真の外部参照は存在しないため、DOM 要素とイベント ハンドラーの両方を削除しても安全です。

古いバージョンの.data()IE では、DOM 要素に追加されたプロパティに特定の問題があり、それらのプロパティ内のデータを含む循環参照を適切に処理しなかったため、必要なときに解放されなかった (リーク) )。 .data()安全で漏れのない文字列であるDOM要素に追加されたプロパティを1つだけ使用することで、これを回避します。その文字列は、DOM 要素に関連付けるすべてのプロパティを含むことができる JavaScript オブジェクトへのキーになります。これらのプロパティはすべて、ブラウザーに循環参照のバグがないプレーンな JavaScript に格納されるため、このようにしてもリークは発生しません。

いくつかの循環参照がまだ存在する可能性があることを理解することが重要であり、それは問題ありません。回避策は、ブラウザにバグがある場所に配置するのではなく、ブラウザが適切に処理する場所に循環参照を移動することです。

于 2012-04-10T17:25:52.470 に答える