8

これがどのように機能するか(または機能しないか)を理解するために、ここで助けが必要です。

  1. Web ページで、ノードのクリック イベント リスナーを作成します。
  2. リスナー内で、ノードをそれ自体のプロパティとして設定するランダム クラスのインスタンスを作成します。したがって、var classInstanceがインスタンスの場合、 のようにノードにアクセスできますclassInstance.rootNode
  3. リスナーが起動すると、ajax リクエストをセットアップし、classInstanceクロージャを維持して ajax レスポンスを渡し、classInstanceそれを使用してrootNodeのスタイルやコンテンツなどを変更します。

私の質問は、 を使い終わったらclassInstance、他にそれを参照するものは何もないと仮定し、それ自体で、それ自体のクロージャーに他に何も保持しないと仮定すると、ガベージコレクターはそれを処分しますか? そうでない場合、どうすれば廃棄するようにマークできますか?

4

2 に答える 2

7

@Beetroot-Beetroot の疑問 (確かに、私もそうです) に応えて、さらに掘り下げました。このフィドルを設定し、chrome dev-tools のタイムラインこの記事をガイドラインとして使用しました。フィドルでは、2 つのほぼ同一のハンドラーが 2 つの日付オブジェクトでクロージャーを作成します。最初は のみを参照aし、2 番目は と の両方aを参照しbます。どちらの場合も、a実際に公開できるのは (ハードコードされた値) だけですが、最初のクロージャは使用するメモリが大幅に少なくなります。これが JIC (ジャスト イン タイム コンパイル) によるものなのか、V8 の JS 最適化ウィザードによるものなのか、はっきりとは言えません。しかし、私が読んだことから、V8 の GC が割り当てを解除bするのは、tst関数は戻りますが、2 番目のケース (戻り時にbar参照) ではできません。これはそれほど風変わりではないと感じています。FF や IE でさえ同様に機能することを知っても、まったく驚かないでしょう。完全を期すために、おそらく関係のないこの更新を追加しました。これは、開発ツールに関するGoogleのドキュメントへのリンクがある種の付加価値であると感じているためです。btst2


簡単な経験則として、依存classInstance関係があります。変数を参照できない限り、それ自体の循環参照に関係なく、GC する必要があります。ここで説明したものと同様に、かなり多くの構造をテストしました。おそらく
クロージャーとメモリリークはそれほど一般的ではないか、簡単に手に入れることができないことがわかりました(少なくとも、もうそうではありません)。

しかし、受け入れられた答えが言うように、どのコードがいつリークするかを知ることはほとんど不可能です.
あなたの質問をもう一度読んで、私は言います:いいえ、あなたはメモリをリークするつもりはありません.classInstance変数はグローバルスコープで作成されていませんが、さまざまな関数(したがってさまざまなスコープ)に渡されています. これらのスコープは、関数が戻るたびに分解されます。classInstance別の関数/スコープに渡された場合、GC されません。ただし、参照する最後の関数が戻るとすぐにclassInstance、オブジェクトは GC のマークが付けられます。確かに循環参照かもしれませんが、独自のスコープ以外からはアクセスできない参照です。
それを実際に閉鎖と呼ぶこともできません。閉鎖は、何らかの形で露出がある場合に発生します。あなたの例では起こっていません。

私はこのようなことを説明するのはばかげていますが、要約するだけです:

var foo = (function()
{
    var a, b, c, d;
    return function()
    {
        return a;
    }
})();

GC は mem と参照の割り当てを解除しbますc:dそれらは範囲外にあり、それらにアクセスする方法はありません...

var foo = (function()
{
    var a, b, c, d;
    return function()
    {
        a.getB = function()
        {
            return b;
        }
        a.getSelf = function()
        {
            return a;//or return this;
        }
        return a;
    }
})();
//some code
foo = new Date();//

この場合、b明らかな理由から、どちらも GC されません。およびをfoo公開します。ここで、は循環参照を含むオブジェクトです。とすぐに、への参照が失われます。確かに、まだ自分自身を参照していますが、もはや公開されていません。好きなものを参照できます。ほとんどのブラウザーは気にせず、GCと. 実際、Chrome、FF、およびIE8 はすべて、上記のコードを完全に GC することを確認しました...心配はいりません。abafoo = new Date()fooaaaab

于 2012-09-27T11:15:07.973 に答える
2

私はこの問題の専門家ではありませんが、GC がそれを処分しないと確信しています。実際には、イベント リスナーと DOM ノードの間に循環参照を作成したため、おそらくそうなることはありません。ガベージ コレクションを可能にするには、これらの参照 (イベント リスナーおよび/または rootNode) の一方または両方を未定義または null に設定する必要があります。

それでも、これらの classInstances を多数作成している場合、またはページの存続期間中に複数回作成できる場合にのみ、これについて心配します。そうでなければ、それは不必要な最適化です。

于 2012-09-27T10:55:52.170 に答える