JavaScriptガベージコレクションとは何ですか?より良いコードを書くために、WebプログラマーがJavaScriptガベージコレクションについて理解するために何が重要ですか?
JavaScriptガベージコレクションとは何ですか?より良いコードを書くために、WebプログラマーがJavaScriptガベージコレクションについて理解するために何が重要ですか?
回答:
Eric Lippertがしばらく前にこのテーマに関する詳細なブログ投稿を書きました(さらにVBScriptと比較しています)。より正確には、JavaScriptによく似ていますが、ECMAScriptのMicrosoft独自の実装であるJScriptについて書いています。Internet ExplorerのJavaScriptエンジンの動作の大部分は同じであると想定できると思います。もちろん、実装はブラウザーによって異なりますが、多くの一般的な原則を採用して他のブラウザーに適用できると思います。
そのページから引用:
JScriptは非世代のマークアンドスイープガベージコレクターを使用します。それはこのように動作します:
「スコープ内」にあるすべての変数は「スカベンジャー」と呼ばれます。スカベンジャーは、数値、オブジェクト、文字列などを参照できます。スカベンジャーのリストを保持しています-変数は、スコープに入るとscavリストに移動し、スコープから出るとscavリストから移動します。
時々、ガベージコレクターが実行されます。まず、すべてのオブジェクト、変数、文字列など、GCによって追跡されるすべてのメモリに「マーク」を付けます。(JScriptはVARIANTデータ構造を内部で使用し、その構造には未使用のビットがたくさんあるため、そのうちの1つを設定します。)
次に、スカベンジャーのマークと、スカベンジャーリファレンスの推移的な閉鎖をクリアします。したがって、スカベンジャーオブジェクトが非スカベンジャーオブジェクトを参照する場合、非スカベンジャーのビットとそれが参照するすべてのビットをクリアします。(私は以前の投稿とは異なる意味で「閉鎖」という言葉を使用しています。)
この時点で、まだマークされているすべてのメモリが割り当てられたメモリであり、スコープ内の変数からのパスでは到達できないことがわかります。これらのオブジェクトはすべて、自分自身を破棄するように指示され、循環参照を破棄します。
ガベージコレクションの主な目的は、プログラマーが作成して使用するオブジェクトのメモリ管理について心配しないようにすることですが、もちろんそれを回避することはできません。 。
歴史的注記:回答の以前の改訂では、delete
演算子への誤った参照がありました。JavaScript では、delete
演算子はオブジェクトからプロパティを削除しdelete
、C / C ++ とはまったく異なります。
delete
あります。たとえば、最初の例では、ではなく、delete foo
最初にイベントリスナーを削除してからwindow.removeEventListener()
、を使用foo = null
して変数を上書きする必要があります。IEではdelete window.foo
(グローバルではないがdelete foo
)機能しましたfoo
が、それでもFFやOperaでは機能しませんでした
delete
は単項演算子(式)であり、ステートメント(つまり:)ではありませんdelete 0, delete 0, delete 3
。式ステートメントで表現すると、ステートメントのように見えます。
DOMオブジェクトが関係する場合は循環参照に注意してください。
オブジェクトへのアクティブな参照がない場合にのみメモリを再利用できることに注意してください。一部の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
、イベントハンドラーが存在する限り収集できません。この問題を解決するにはいくつかの方法、例えば設定があるbigString = null
の終わりにinit()
(delete
ローカル変数や関数の引数では動作しません:delete
オブジェクトから削除しプロパティ、および変数オブジェクトにアクセスできないが- strictモードでES5でもスローされますReferenceError
、あなたがしようとした場合ローカル変数を削除するには!)
メモリの消費を気にする場合は、不要なクロージャをできるだけ避けることをお勧めします。
ブログから引用した良い引用
DOMコンポーネントは、JScriptコンポーネントと同様に「ガベージコレクション」されます。つまり、どちらかのコンポーネント内にオブジェクトを作成し、そのオブジェクトの追跡を失った場合、最終的にクリーンアップされます。
例えば:
function makeABigObject() {
var bigArray = new Array(20000);
}
その関数を呼び出すと、JScriptコンポーネントは、関数内でアクセス可能なオブジェクト(bigArrayという名前)を作成します。ただし、関数が戻るとすぐに、それを参照する方法がないため、bigArrayの「トラックを失います」。さて、JScriptコンポーネントは、それを追跡できなくなったことを認識し、bigArrayがクリーンアップされ、そのメモリが解放されます。同じようなことがDOMコンポーネントでも機能します。と言うdocument.createElement('div')
か、それに似たものであれば、DOMコンポーネントがオブジェクトを作成します。どういうわけかそのオブジェクトを追跡できなくなると、DOMコンポーネントは関連するオブジェクトをクリーンアップします。
私の知る限り、JavaScriptのオブジェクトは、オブジェクトへの参照が残っていない場合、定期的にガベージコレクションされます。これは自動的に行われる処理ですが、C ++レベルでそれがどのように機能するかについてさらに詳しく知りたい場合は、WebKitまたはV8のソースコードを確認することをお勧めします。
通常、それについて考える必要はありませんが、IE 5.5やIE 6の初期バージョンなどの古いブラウザーでは、おそらく現在のバージョンでは、クロージャーは循環チェックを作成し、チェックされていない場合は最終的にメモリを消費します。クロージャーについて私が意味する特定のケースでは、それは、DOMオブジェクトへのJavaScript参照と、JavaScriptオブジェクトを参照するDOMオブジェクトへのオブジェクトを追加したときでした。基本的にそれを収集することはできず、最終的にループしてクラッシュを作成したテストアプリでOSが不安定になります。実際にはこれらのリークは通常小さなものですが、コードをクリーンに保つには、DOMオブジェクトへのJavaScript参照を削除する必要があります。
通常、特にモバイルWeb開発では、deleteキーワードを使用して、受け取ったJSONデータなどの大きなオブジェクトを即座に逆参照し、それを使用して必要なことをすべて実行することをお勧めします。これにより、GCの次のスイープがそのオブジェクトを削除し、そのメモリを解放します。
mark-and-sweep
スタイルのアルゴリズムがこれを処理します。
ガベージコレクション(GC)は、不要になったオブジェクトを削除することによる自動メモリ管理の形式です。
メモリを処理するプロセスはすべて、次の手順に従います。
1-必要なメモリ領域を割り当てます
2-いくつかの処理を行います
3-このメモリ空間を解放する
不要になったオブジェクトを検出するために使用される2つの主要なアルゴリズムがあります。
参照カウントガベージコレクション:このアルゴリズムは、「オブジェクトはもう必要ありません」の定義を「オブジェクトはそれを参照する他のオブジェクトを持たない」に減らします。参照ポイントがない場合、オブジェクトは削除されます
マークアンドスイープアルゴリズム:各オブジェクトをルートソースに接続します。オブジェクトはルートや他のオブジェクトに接続しません。このオブジェクトは削除されます。
現在、2番目のアルゴリズムを使用する最新のブラウザーのほとんど。
「コンピューターサイエンスでは、ガベージコレクション(GC)は自動メモリ管理の一種です。ガベージコレクター(または単にコレクター)は、アプリケーションによって再度アクセスまたは変更されることのないオブジェクトによって使用されるガベージまたはメモリを再利用しようとします。」
すべてのJavaScriptエンジンには独自のガベージコレクターがあり、異なる場合があります。彼らは彼らがすることになっていることをするだけなので、ほとんどの場合あなたはそれらに対処する必要はありません。
より優れたコードを書くには、プログラミングの原則、言語、特定の実装をどれだけ知っているかにかかっています。
JavaScriptガベージコレクションとは何ですか?
これをチェック
より良いコードを書くために、WebプログラマーがJavaScriptガベージコレクションについて理解するために何が重要ですか?
Javascriptでは、メモリの割り当てと割り当て解除は関係ありません。問題全体はJavascriptインタプリタに要求されます。リークはまだJavaScriptで可能ですが、インタプリタのバグです。このトピックに興味がある場合は、www.memorymanagement.orgで詳細を読むことができます。
参照型は、オブジェクトが割り当てられている変数に直接オブジェクトを格納しないため、この例のオブジェクト変数には、実際にはオブジェクトインスタンスが含まれていません。代わりに、オブジェクトが存在するメモリ内の場所へのポインタ(または参照)を保持します
var object = new Object();
ある変数を別の変数に割り当てると、各変数はポインターのコピーを取得しますが、どちらもメモリー内の同じオブジェクトを参照します。
var object1 = new Object();
var object2 = object1;
JavaScriptはガベージコレクションされた言語であるため、参照型を使用するときにメモリ割り当てについて心配する必要はありません。ただし、不要になったオブジェクトを逆参照して、ガベージコレクターがそのメモリを解放できるようにすることをお勧めします。これを行う最良の方法は、オブジェクト変数をnullに設定することです。
var object1 = new Object();
// do something
object1 = null; // dereference
オブジェクトの逆参照は、何百万ものオブジェクトを使用する非常に大規模なアプリケーションでは特に重要です。
オブジェクト指向JavaScriptの原則から-NICHOLAS C. ZAKAS