11

Web アプリケーション (単一の完全な ajax ページ) の存続期間中に再作成し続ける JavaScript クロージャーがあります。

メモリリークが発生しているかどうかを知りたいです。

JSFIDDLEの例を次に示します。

問題のコード:

function CreateLinks() {

    var ul = $("<ul></ul>").appendTo('div#links');

    for (var i in myLinks) {

        var li = $('<li>' + myLinks[i].name + '</li>').appendTo(ul);

        //closure starts here
        (function (value) {
            li.click(function (e) {
                $('div#info').append('<label>' + value + '</label><br />');
                RecreateLinks();
            });
        })(myLinks[i].value);

    }
}
4

2 に答える 2

2

関数内で複数のclickハンドラーをバインドしないように注意すれば、問題はありません。RecreateLinks()これは、既存のノードのバインドを明示的に解除するか、DOMノードを削除するか、複数のclickハンドラーを追加しないようにすることで実行できます。

ブラウザはメモリ割り当て戦略で良くなっていますが、あまり多くを想定するべきではありません。メモリ使用量が大きな懸念事項である場合は、ガベージコレクションが行われるかどうかわからないクロージャをあまり多く作成しないようにしてください。そのようなアプローチの1つは.data()、値オブジェクトを格納するために使用し、クロージャの代わりに汎用クリックハンドラーを使用することです。

JavaScriptのプロファイリングはそれほど単純ではありません。Chromeには、CPUとデータのパフォーマンスを監視できるプロファイルツールがあります。これにより、予想されるメモリ消費量をかなり正確に把握できますが、Chromeがすべてのブラウザであるとは限りません。この点に注意してください。

于 2012-10-01T19:06:07.587 に答える
1

ブラウザーがどれだけ賢いかによっては、「myLinks[i].value」<li>をクロージャー経由で渡すよりも属性にしたほうがよい場合があります。特定のダム ブラウザでは、イベント ハンドラがそのスコープ外から変数を参照すると、ガベージ コレクションの問題が発生します。JavaScript と DOM は 2 つの異なる GC を実行しますが、JS は DOM 要素/イベントハンドラーがなくなったこと、および変数が使用されなくなったことを認識していません。この問題は、アタッチされている要素を単に破棄するのではなく、javascript を介してイベント ハンドラーを適切に削除することによって解決される場合があります。

次のようなもの:

li.attr('lvalue',myLinks[i].value);
...
var value = $(this).attr('lvalue');

この設定により、次の使用も可能になります

$('#links > ul > li').live('click',function(){...});

これにより、毎回個々のイベントを追加する必要がなくなります。

于 2012-10-01T19:17:08.680 に答える