7

私は現在、純粋な JavaScript であり、jQuery および jQuery UI ライブラリに大きく依存する Web サイトを開発しています (このサイトは一般ユーザーによる使用を意図していないため、プログレッシブ エンハンスメントはこのプロジェクトの厳密な要件ではありません)。次のコードを実行すると、重大なメモリ リークが発生します。

oDialogBox = $("<div>...</div>");
/* Add useful things to the dialog box here */
oDialogBox.appendTo("body");
oDialogBox.dialog({
    /* Other dialog box settings here */
    close: function(event, ui) {
        oDialogBox.dialog("destroy");
        oDialogBox.remove();
        oDialogBox = null;
    }
});

このダイアログ ボックスではいつでも、jQuery UI ボタン​​、マルチセレクト (Eric Hynds によって作成されたマルチセレクト ウィジェットによる)、およびクリック イベント ハンドラーの多数のインスタンスを作成、削除、および変更しています。jQuery UI ドキュメントによると、oDialogBox で .remove() を呼び出すと、すべての子ウィジェットのバインドが解除され、削除されるはずです。しかし、切り離された DOM ツリーには、GC が収集していない大量のガベージ要素が表示されます。

安全に終わらせる必要のある大量のクロージャーを見逃している可能性が高いです。次のことを行うにはどうすればよいですか。

1) 特定の切り離された DOM オブジェクトを存続させているクロージャーを特定するにはどうすればよいですか (Firefox または Chrome のいずれか)。

2) クロージャーの完全なセットが特定されたと仮定すると、ガベージ コレクションの DOM 要素を確実にマークするために、変数を null にする以外に何かする必要がありますか?

3) ページに保存されている配列のリストが巨大で、GC によって収集されていない DOM 要素への参照が含まれていることにも気付きました。JavaScript から配列を消去し、すべての要素を削除対象としてマークできるようにするための文書化されたベスト プラクティスはありますか? (注: これは、メモリ リークの原因として現在最も疑わしいものです)

4

1 に答える 1

1

#1 については、適切な回答が得られないことを残念に思います。ここ数年で開発ツールがどれほど優れたものになったかを考えても、私自身はこれに適した本当に優れたツールを見つけていません。私ができる最善のアドバイスは、物事を可能な限り最小の範囲に保つことです。物事が逃げない場合は、通常、参照がどこにある必要があるかを単純に把握する方が簡単です。

#2に関しては、さらに懸念がある可能性があります。変数によって参照されるオブジェクトv1がある関数の空き変数を閉じる場合、他の関数で別の変数が閉じるv1場合、それらを削除してもガベージ コレクションの対象にすることはできません。したがって、「クロージャーの完全なセット」を本当に意味するのであれば、すべて設定されているはずです。しかし、これは毛むくじゃらになるかもしれません。繰り返しますが、ほとんどのオブジェクトが狭いスコープでのみ参照を持っている場合、これらの問題はそれほど深刻ではありません。v2v1

#3 については、どのような種類の配列について話し合っていますか? それが jQuery コレクションの場合は、単純にコレクションが多すぎるのかもしれません。それらが長期間存在する唯一の理由は、イベント ハンドラーをそれらにバインドすることです。これは、ほとんどの場合、親要素のイベント委任によってより適切に処理されます。あなたがカスタム配列を所有している場合、それらへの参照をかなりの時間持続する配列に格納する正当な理由は本当にありますか? 私はめったに見つけたことがありません。

于 2012-12-06T01:09:20.917 に答える