web-dev-qa-db-ja.com

JavaScriptガベージコレクションとは何ですか?

JavaScriptガベージコレクションとは何ですか?より良いコードを書くために、WebプログラマーがJavaScriptガベージコレクションについて理解するために重要なことは何ですか?

290
user290

Eric Lippertは の詳細なブログ投稿 をしばらく前に書いています(さらにVBScriptと比較しています) =)。より正確には、彼は JScript について書いています。これはMicrosoftのECMAScriptの実装ですが、JavaScriptに非常に似ています。 Internet ExplorerのJavaScriptエンジンの動作の大部分が同じであると仮定できると思います。もちろん、実装はブラウザーごとに異なりますが、多くの一般的な原則を採用して他のブラウザーに適用できると思われます。

そのページから引用:

JScriptは、非世代のマークアンドスイープガベージコレクターを使用します。それはこのように動作します:

  • 「スコープ内」にあるすべての変数は「スカベンジャー」と呼ばれます。スカベンジャーは、数字、オブジェクト、文字列などを指します。スカベンジャーのリストを保持しています。変数は、スコープに入ったときにscavリストに移動し、スコープから外れたときにscavリストから移動します。

  • ガベージコレクターが時々実行されます。まず、すべてのオブジェクト、変数、文字列など、GCによって追跡されるすべてのメモリに「マーク」を付けます。 (JScriptは内部でVARIANTデータ構造を使用し、その構造には余分な未使用ビットがたくさんあるため、そのうちの1つを設定するだけです。)

  • 第二に、スカベンジャーのマークとスカベンジャー参照の推移的な閉鎖をクリアします。そのため、スカベンジャーオブジェクトが非スカベンジャーオブジェクトを参照している場合、非スカベンジャーとそれが参照するすべてのビットをクリアします。 (以前の投稿とは異なる意味で「クロージャ」という言葉を使用しています。)

  • この時点で、まだマークされているすべてのメモリには、スコープ内変数からのパスで到達できないメモリが割り当てられていることがわかります。これらのオブジェクトはすべて、自身を破棄するように指示されているため、循環参照はすべて破棄されます。

ガベージコレクションの主な目的は、プログラマが作成および使用するオブジェクトのメモリ管理を心配することですnot。もちろん、回避することはありませんが、少なくともガベージコレクションの仕組みの大まかなアイデア。

注意すべきいくつかの特定のポイントがあります。 Apple開発者サイトには いくつかのガイドライン があります。そこから2つの重要なもの:

  • 削除ステートメントを使用します。新しいステートメントを使用してオブジェクトを作成するたびに、それを削除ステートメントとペアにします。これにより、プロパティ名を含むオブジェクトに関連付けられたすべてのメモリがガベージコレクションに使用できるようになります。削除ステートメントについては、「オブジェクトの解放」で詳しく説明します。
  • Varキーワードを使用します。 varキーワードなしで作成された変数は、グローバルスコープで作成され、ガベージコレクションの対象とはならず、メモリリークの可能性があります。

プラクティスはすべてのJavaScriptエンジン(異なるブラウザー)に適用されるはずですが、これはAppleサイトからのものであるため、may Safariに多少固有のものです。 (おそらく誰かがそれを明確にすることができますか?)

お役に立てば幸いです。

188
Noldorin

DOMオブジェクトが関係する場合、循環参照に注意してください。

JavaScriptのメモリリークパターン

オブジェクトへのアクティブな参照がない場合にのみ、メモリを再利用できることに注意してください。一部のJSエンジンは、どの変数が実際に内部関数で参照されているかをチェックせず、囲んでいる関数のすべてのローカル変数を保持するため、これはクロージャーとイベントハンドラーの一般的な落とし穴です。

以下に簡単な例を示します。

function init() {
    var bigString = new Array(1000).join('xxx');
    var foo = document.getElementById('foo');
    foo.onclick = function() {
        // this might create a closure over `bigString`,
        // even if `bigString` isn't referenced anywhere!
    };
}

単純なJS実装は、イベントハンドラーが存在する限りbigStringを収集できません。この問題を解決するには、いくつかの方法があります。たとえば、init()の最後にbigString = nullを設定すると(deleteはローカル変数および関数引数に対して機能しません。deleteはオブジェクトからプロパティを削除し、ローカル変数を削除しようとすると、ReferenceError!)。

メモリの消費を気にする場合は、不要な閉鎖を可能な限り避けることをお勧めします。

52
Christoph

ブログから引用した良い引用

DOMコンポーネントは、JScriptコンポーネントと同様に「ガベージコレクト」されます。つまり、いずれかのコンポーネント内でオブジェクトを作成し、そのオブジェクトを追跡できなくなった場合、最終的にクリーンアップされます。

例えば:

function makeABigObject() {
var bigArray = new Array(20000);
}

その関数を呼び出すと、JScriptコンポーネントは、関数内でアクセス可能なオブジェクト(bigArrayという名前)を作成します。ただし、関数が返るとすぐに、bigArrayを「失う」ことになります。これは、それを参照する方法がないためです。さて、JScriptコンポーネントは、あなたがそれを追跡できなくなったことを認識します。そのため、bigArrayはクリーンアップされ、メモリが回収されます。同じようなことがDOMコンポーネントでも機能します。 document.createElement('div')、または同様のものを言うと、DOMコンポーネントがオブジェクトを作成します。何らかの形でそのオブジェクトを追跡できなくなると、DOMコンポーネントが関連オブジェクトをクリーンアップします。

15
TStamper

私の知る限り、オブジェクトへの参照が残っていない場合、JavaScriptのオブジェクトは定期的にガベージコレクションされます。自動的に行われますが、C++レベルでどのように機能するかについて詳しく知りたい場合は、 WebKit または V8ソースコード

通常、それについて考える必要はありませんが、IE 5.5やIE 6の初期バージョン、おそらく現在のバージョンのような古いブラウザーでは、クロージャーは次のような循環参照を作成します。チェックを外すと、メモリを消費してしまいます。クロージャーについての特定のケースでは、domオブジェクトにJavaScript参照を追加し、JavaScriptオブジェクトを参照するDOMオブジェクトにオブジェクトを追加したときでした。基本的には収集できず、最終的にループしてクラッシュを引き起こすテストアプリでOSが不安定になります。実際には、これらのリークは通常は小さいですが、コードをクリーンに保つには、DOMオブジェクトへのJavaScript参照を削除する必要があります。

通常、deleteキーワードを使用して、特にモバイルWeb開発において、受け取ったJSONデータなどのビッグオブジェクトをすぐに参照解除し、必要な処理を実行することをお勧めします。これにより、GCの次のスイープによりそのオブジェクトが削除され、メモリが解放されます。

13
Heat Miser

ガベージコレクション(GC)は、不要になったオブジェクトを削除することによる自動メモリ管理の一種です。

メモリを処理するプロセスは次の手順に従います。

1-必要なメモリスペースを割り当てる

2-何らかの処理を行う

3-このメモリ空間を解放する

不要になったオブジェクトを検出するために使用される2つの主要なアルゴリズムがあります。

参照カウントガベージコレクション:このアルゴリズムは、「オブジェクトはもう必要ありません」の定義を「オブジェクトがそれを参照する他のオブジェクトを持たない」に減らします。参照ポイントがない場合、オブジェクトは削除されます

マークアンドスイープアルゴリズム:各オブジェクトをルートソースに接続します。オブジェクトはルートまたは他のオブジェクトに接続しません。このオブジェクトは削除されます。

現在、2番目のアルゴリズムを使用している最新のブラウザ。

6

「コンピュータサイエンスでは、ガベージコレクション(GC)は自動メモリ管理の一種です。ガベージコレクタ、または単なるコレクタは、ガベージ、またはアプリケーションによって再びアクセスまたは変更されないオブジェクトによって使用されるメモリを回収しようとします。」

すべてのJavaScriptエンジンには独自のガベージコレクターがあり、異なる場合があります。ほとんどの場合、彼らは彼らがやるべきことをするだけなので、それらに対処する必要はありません。

より良いコードを書くことは、主にプログラミングの原則、言語、特定の実装をどれだけ知っているかに依存します。

4
mtasic85

JavaScriptガベージコレクションとは何ですか?

チェック this

より良いコードを書くために、WebプログラマーがJavaScriptガベージコレクションについて理解するために重要なことは何ですか?

Javascriptでは、メモリの割り当てと割り当て解除は気にしません。すべての問題は、Javascriptインタープリターに要求されます。リークはJavascriptでまだ可能ですが、インタープリターのバグです。このトピックに興味がある場合は、 www.memorymanagement.org で詳細を読むことができます。

1
dfa

Windowsでは、 Drip.exe を使用してメモリリークを見つけるか、空きmemルーチンが機能するかどうかを確認できます。

WebサイトのURLを入力するだけで、統合されたIEレンダラーのメモリ消費量が表示されます。その後、リフレッシュを押すと、メモリが増加した場合、Webページのどこかにメモリリークが見つかりました。しかし、これはメモリを解放するルーチンがIEで機能するかどうかを確認するのにも非常に便利です。

1
powtac

参照型は、割り当てられた変数にオブジェクトを直接保存しないため、この例のオブジェクト変数には実際にオブジェクトインスタンスが含まれていません。代わりに、オブジェクトが存在するメモリ内の場所へのポインター(または参照)を保持します

var object = new Object();

ある変数を別の変数に割り当てると、各変数はポインターのコピーを取得しますが、どちらもメモリ内の同じオブジェクトを引き続き参照します。

var object1 = new Object();
var object2 = object1;

Two variables pointing to one object

JavaScriptはgarbage-collected言語であるため、参照型を使用する際にメモリの割り当てを心配する必要はありません。ただし、ガベージコレクターがそのメモリを解放できるように、不要になったオブジェクトをdereferenceすることをお勧めします。これを行う最良の方法は、オブジェクト変数をnullに設定することです。

var object1 = new Object();
// do something
object1 = null; // dereference

オブジェクトの逆参照は、数百万のオブジェクトを使用する非常に大きなアプリケーションで特に重要です。

オブジェクト指向JavaScriptの原則から-NICHOLAS C. ZAKAS

0
Ani Naslyan