13

jQueryメソッドrequestAnimationFrameの呼び出しを含むループでゲームを構築しています。html()ゲーム アクションの横にあるステータス ウィンドウのテキストを更新するだけです。

Chrome のタイムライン モニターで、DOM ノードが 1 分間に何千も上昇していることに気付きました。そして、コードを次のように変更すると:

// creates a ton of DOM nodes
$("#readout").html(data);

// DOM nodes does not increase over time
document.getElementById('readout').innerHTML = data;

「メモリリーク」はなくなります。

4

2 に答える 2

7

簡単な答え: いいえ。

長い答え: ページ/コードで何か他のことが起こっている可能性があります。

一般に、メモリ リークは、Javascript エンジンと DOM の間の循環参照が原因で発生します。例えば:

var div = document.getElementById('divId');
div.onclick = function() {
    doSomething(div);
};

スクリプトは、ページ上の div への参照を取得します。これまでのところ、問題ありません。次の行は、関数を DOM のイベント ハンドラーに割り当て、DOM から Javascript エンジンへの参照を作成します - リークの途中です。関数本体はクロージャーを作成するタグを使用します。タグ参照は、将来の呼び出しのために関数とともに保持されます。これで、タグ -> 関数 (DOM -> JS) と関数 -> タグ (JS -> DOM) の間の循環参照が完了するため、ブラウザのプロセスが破棄されるまで 2 つはメモリ内に留まります。

したがって、あなたが言及したコードのいずれかの行がリークするためには、上記のようにイベントが添付されたタグ (または同様のパターンに従うデータ) を削除する必要があります。しかし、jQuery の .html(string) は、これらを防ぐために最善を尽くします。

// Remove element nodes and prevent memory leaks
elem = this[i] || {};
if ( elem.nodeType === 1 ) {
    jQuery.cleanData( getAll( elem, false ) );
    elem.innerHTML = value;
}

したがって、.html(string) を実行しているタグ内のすべてのタグをループし、それらに対して cleanData() を実行すると、次のようになります。

jQuery.removeEvent( elem, type, data.handle );

したがって、漏れを防ぎます。

したがって、ブラウザの組み込み .innerHTMLではなく、このメソッドでメモリをリークするには、非常にあいまいなブラウザのバグをトリガーする必要があります (ほとんどありそうにないようです)。 jQuery の .html(string) の場合。

于 2013-04-04T09:59:28.043 に答える
2

.empty().html(...)ただの代わりに常に使用する.html()

.empty()削除しようとしている DOM オブジェクトからイベント リスナーのバインドを解除し、適切に削除します。

于 2013-05-06T19:11:11.177 に答える