2

しばらくの間、クロージャに関する JS ガベージ コレクションのルールについて確信が持てなかったので、質問したほうがよいと思います... jQuery の$.eachメソッドを使用することに興味がある良い例を次に示します。

storeSelection: function() {
    var enabledIds = {};

    $.each(this.nodes, function(index, node) {
        if (node.enabled) {
            enabledIds[ node.id ] = true;
        }
    });

    this.selection = enabledIds;
}

もちろん、上記のスニペットはオブジェクト リテラルの一部です。そこで、有効なアイテムの ID を配列内に格納する新しいオブジェクトを外側の関数の先頭に作成しました。jQuery の.each()メソッドを使用して、アイテムの配列をループし、有効な ID をログに記録しています。最後に、選択範囲を親オブジェクトのメンバーとして保存します。

enabledIds私の質問には、外部スコープからオブジェクトを参照する内部関数が含まれます。くっついてしまうのでenabledIds、内部機能が溜まらないのでしょうか?内部関数の最後にクリアされるのは単なる変数なので、そうではないと思いますよね?リークになるには、次のように、内部関数が外部オブジェクトへのハード参照を作成する必要があると思います。

$.each(this.nodes, function(index, node) {
    this.badIdea = enabledIds;
    if (node.enabled) {
        enabledIds[ node.id ] = true;
    }
});

しかし... 私はいつもこのルールにうんざりしています。この混乱を解消するための助けをいただければ幸いです。

4

2 に答える 2

3

いいえ、2番目の例でさえリークを引き起こすのに十分ではありません。badIdeaは個々のノードに接続されており、$.eachブロックは終了してガベージコレクションされます。最近のすべてのブラウザは、javascriptガベージコレクションに「マークアンドスイープ」アルゴリズムを使用します。これは、親から子への関連付けに従い、「到達不能」、つまりこれらのツリーの1つからアクセスできないものを収集します。

于 2012-05-22T17:07:11.280 に答える
1

そうです、内部関数 ( indexnode) からの変数は、もうアクセスできないため、ガベージ コレクションされます。

この例では、アクセスできますbigstrか?

a = function() {
        var bigstr = new Array(1000000).join('x');
        return function() { return bigstr; };
    }();

はい、できるa()ので、収集されません。この例はどうですか:

a = function() {
        var bigstr = new Array(1000000).join('x');
        return function(n) { return eval(n); };
    }();

繰り返しますが、次のことができますa('bigstr')

しかし、これはどうですか:

a = function() {
        var smallstr = 'x';
        var bigstr = new Array(1000000).join('x');
        return function(n) { return smallstr; };
    }();

もうアクセスできず、ガベージ コレクションの候補です。

于 2012-05-22T17:20:05.800 に答える