1

JavaScript のガベージ コレクションと、それを促進する最善の方法について、かなり混乱しています。

私が知りたいのは、特定のパターンに関連しています。パターン自体が良いアイデアか悪いアイデアかには興味がありません。ブラウザーのガベージ コレクターがどのように応答するか、つまり、参照が解放されて収集されるか、またはリークが発生するかだけに興味があります。

次のパターンを想像してください。

   TEST = {     
                init : function(){                        
                      this.cache = {
                           element : $('#element')
                      };
                },
                func1 : function(){
                       this.cache.element.show();                     
                },
                func2 : function(){                                            
                       TEST.cache.element.show(); 
                },
                func3 : function(){
                       var self = this;                      
                       self.cache.element.show(); 
                },
                func4 : function(){
                       var element = this.cache.element;
                       element.show();
                }
                func5 : function(){
                        this.auxfunc(this.cache.element);
                }
                auxfunc1 : function(el){
                         el.show();
                }
                func6 : function(){
                       var el = getElement();
                       el.show();
                }
                getElement : function(){
                       return this.cache.element;
                }
    }

on page loadTEST.init()が呼び出されたとします。

その後、さまざまな時点でさまざまな関数が呼び出されます。

私が知りたいのは、上記の方法で、初期化時に要素やオブジェクトなどをキャッシュし、アプリケーションの存続期間全体でそれらを参照することが、ブラウザーのガベージ コレクターにプラスまたはマイナスの影響を与えるかどうかです。

違いはありますか?ガベージ コレクションを促進するのに最適な方法はどれですか? それらは漏れを引き起こしますか?循環参照はありますか?もしそうならどこ?

4

1 に答える 1

5

このコード自体がメモリ リークを引き起こすことはありません。特に最新のブラウザではそうではありません。スクリプトには他にもたくさんあるように、それは単なるオブジェクトです。それはすべて、参照する場所、方法、および期間によって異なります。

基本的なルールは、オブジェクトがコード内のどこからも (直接/変数によって、または間接的に/スコープにアクセスするクロージャーを通じて) 参照されなくなったときは常に、GC がフラグを立ててスワイプすることです。
上記のコードを使用して、TESTそれが参照するオブジェクト リテラルに別のものを代入すると、元のオブジェクトを参照する変数が他になければ、GC される可能性があります。

もちろん、JS でのメモリ リークの予測は不正確な科学です。私の経験では、一部の人が信じているほど一般的ではありません。Firebug、Chrome のコンソール (プロファイラー)、および IE デバッガーは、長い道のりを歩んでいます。

しばらく前に、この問題をさらに掘り下げて、この質問に至りました。おそらく、いくつかのリンクと調査結果が役に立ちます...

そうでない場合は、明らかなリークを回避するためのヒントをいくつか紹介します。

  • グローバル変数を使用しないでください (実際には永久にメモリ リークするわけではありませんが、スクリプトが実行されている限りメモリ リークが発生します)。
  • イベント ハンドラーをグローバル オブジェクトにアタッチしないでください (グローバル オブジェクトが完全にアンロードされることwindow.onloadはないため、==> IE <9 で mem がリークするため、イベント ハンドラーは GC されません)。
  • スクリプトを巨大な IIFE でラップし、可能な限り厳密モードを使用してください。このようにして、アンロード時に全体を GC できるスコープを作成します。
  • テスト、テスト、そしてまたテスト。この件に関して読んだすべてのブログ投稿を信じないでください。昨年何か問題があったとしても、今日はそうである必要はありません。この回答は、あなたがこれを読む頃にはもう 100% 正確ではないかもしれません。または、今朝、JS GC の奇跡的なパッチが erm... Paris Hilton または他のエイリアンの生命体によって書かれたためです。

ああ、あなたのコメント内の質問に答えるために:集めました?"
答えはノーだ。はオブジェクトthisを参照し、関数はオブジェクトにプロパティを割り当てるため、それ自体はjQオブジェクトを参照する1つのプロパティを持つ別のオブジェクトリテラルです。そのプロパティ ( ) とそれを介してアクセスできるすべてのものは、または. そのオブジェクトを作成すると、TESTinitcahchecachedelete TEST.cachedelete TESTvar cahce = {...};iniクロージャーを使用して特定の変数を間接的に公開している場合を除いて、変数はそのスコープを超えて存続できないため、関数は戻ります。

于 2013-04-25T14:19:16.080 に答える