30

Javascriptエンジンで循環参照がどのように処理されるか詳しく説明できますか?ブラウザやnode.jsにも大きな違いがありますか?Javascript /ガベージコレクタの循環参照

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

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; 

またはガベージコレクタは、このような星座で私たちの世話をする必要がありますか?

答えて

53

半二重ガベージコレクタはサイクルを処理します。

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

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

次に、他のすべてのメモリを取り戻すだけです。

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

リファレンスカウントに基づくさらに多くのプリミティブなGCは、通常、サイクルを検出して中断するアルゴリズムを実装します。

要するに、それは心配するものではありません。 IE6のJavascript GCは実際にはサイクルを処理できませんでした(私は間違っているかもしれませんが、読んでからしばらくありました。IE6に触れてからずっとずっと長くなっていますが)現代的な実装では、問題ない。

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

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

+1

http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml?showone=Closures#Closuresは間違っていますか? – Sandro

+2

@Sandroは私の答えをもう一度読んだ。 :)正気なGCはサイクルをうまく処理します。 IE6より新しいものはすべて正気だと考えることができます。 IE6をサポートする必要がある場合は、サイクルの壊れた処理について心配する必要があります。明らかに、Googleのガイドは、そのような壊れたブラウザがサポートされなければならないという前提で書かれているので、いくつかの追加のフープを飛ばしなければならない。 – jalf

+0

@Sandroこの例では特別なことがあります.DOM要素は循環参照の一部です。一般に、ページを閉じるまで、メモリがリークします。しかし、私が正しくリコールすると、IEが離れて移動するときにDOMへの参照が常に削除されるとは限りません。 (明らかにいくつかのページが壊れていますか?) –