web-dev-qa-db-ja.com

Javascript /ガベージコレクターの循環参照

Javascriptエンジンが循環参照をどのように処理するかを誰かが詳細に説明できますか?ブラウザ間、あるいはnode.js間でさえ大きな違いはありますか?

私が話しているのは、オブジェクト内の明示的な後方/次の参照です。例えば:

_var objA = {
    prop: "foo",
    next: null
};

var objB = {
    prop: "foo",
    prev: null
};

objA.next = objB;
objB.prev = objA;
_

そこに行きます。 console.log( objA )を実行すると、無限のチェーンを作成したことがわかります。大きな問題は、これは悪いことですか?明示的にクリーニングしないと、メモリリークが発生しますか?

だから私たちはしなければなりませんか

_objA.next = null;
objB.prev = null;
_

それとも、ガベージコレクターはこのような星座で私たちの世話をしますか?

40
jAndy

半ばまともなガベージコレクターは、サイクルを処理します。

単純な参照カウントを行う場合にのみ、サイクルが問題になります。

ほとんどのガベージコレクターは、参照カウントを行いません(サイクルを処理できないため、および非効率的であるため)。代わりに、「ルート」(通常はグローバル変数とスタックベースの変数)から始めて、見つけることができるすべての参照に従い、見つけることができるすべてのものを「到達可能」としてマークします。

次に、他のすべてのメモリを再利用するだけです。

サイクルは、同じノードに複数回到達することを意味するだけなので、問題ありません。初回以降、ノードはすでに「到達可能」としてマークされているため、GCはノードがすでに存在していることを認識し、ノードをスキップします。

参照カウントに基づくさらに原始的なGCは、通常、サイクルを検出して中断するアルゴリズムを実装します。

要するに、それはあなたが心配しなければならないことではありません。 IE6のJavascriptGCが実際にサイクルを処理できなかったことを思い出しているようです(間違っている可能性があります。読んでからしばらく経ち、IE6に触れてからずっと長くなっています)が、最近の実装ではそうではありません。問題。

ガベージコレクターの要点は、メモリ管理を抽象化することです。この作業を自分で行う必要がある場合は、GCが壊れています。

最新のガベージコレクションと使用されているマークアンドスイープアルゴリズムの詳細については、 [〜#〜] mdn [〜#〜] を参照してください。

64
jalf