導入
Cなどの低レベルの言語には、malloc()やfree()などの低レベルのメモリ管理プリミティブがあります。一方、JavaScriptのメモリプリミティブは、変数(オブジェクト、文字列など)が作成され、使用されなくなったときに「自動的に」解放されたときに割り当てられます。後者はガベージコレクションと呼ばれます。この「自動」は、JavaScript(およびその他の高レベルの言語)開発者に幻想を与え、幻想を与えています。メモリ管理を無視できます。
メモリライフサイクル
プログラミング言語に関係なく、メモリライフサイクルは基本的に同じです。
1.必要なメモリを割り当てます
2。それを使用します(読み、書きます)
3。PSをリリース:そして「象を冷蔵庫に入れてください」は同じことを意味します
プロセスの最初と2番目の部分は、すべての言語で明確です。最後のステップは低レベルの言語では明確ですが、JavaScriptのような高レベルの言語では、最後のステップは明確ではありません。
JavaScriptのメモリ割り当て
可変初期化
割り当ての問題でプログラマーを悩ませないために、JavaScriptは変数を定義するときにメモリ割り当てを完了します。
コードコピーは次のとおりです。
var n = 123; //数値変数にメモリを割り当てます
var s = "azerty";
var o = {
A:1、
B:ヌル
}; //オブジェクトのメモリを割り当てます
var a = [1、null、 "bra"];
関数f(a){
+ 2を返します。
} //関数にメモリを割り当てる(呼び出し可能なオブジェクト)
//関数式はオブジェクトを割り当てることもできます
someelement.addeventlistener( 'click'、function(){
someelement.style.backgroundcolor = 'blue';
}、 間違い);
関数呼び出しによるメモリ割り当て
一部の関数呼び出しは、オブジェクトメモリを割り当てることになります。
コードコピーは次のとおりです。
var d = new date();
var e = document.createelement( 'div'); // dom要素を割り当てます
一部の方法では、新しい変数または新しいオブジェクトを割り当てます。
コードコピーは次のとおりです。
var s = "azerty";
var S2 = S.Substr(0、3);
// stringは不変であるため、JavaScriptはメモリを割り当てない場合がありますが、範囲0〜3のみを保存します。
var a = ["ouais ouais"、 "nan nan"];
var a2 = ["generation"、 "nan nan"];
var a3 = a.concat(a2);
値の使用
値を使用するプロセスは、実際にはメモリの割り当ての読み取りおよび書き込み操作です。つまり、変数またはオブジェクトのプロパティ値を書き込むことができます。また、関数のパラメーターも渡すことができます。
メモリが不要になったときに解放されます
ほとんどのメモリ管理の問題はこの段階にあります。ここで最も難しい作業は、「割り当てられたメモリが実際にはもう必要ない」を見つけることです。多くの場合、開発者はプログラムのどのメモリが不要になっているかを判断し、解放する必要があります。
高レベルの言語インタープリターには「ゴミコレクター」が埋め込まれており、その主な仕事は、割り当てられたメモリが使用されなくなったときに自動的に解放されるように、メモリの割り当てと使用を追跡することです。特定のメモリを決定する必要があるかどうかを判断することは不可能であるため、このプロセスは近似です(一部のアルゴリズムでは解決できません)。
ゴミリサイクル
上記のように、ある程度のメモリが「もはや必要ない」かどうかを自動的に探すという問題は、決定することが不可能です。したがって、ガベージコレクションの実装は、制限のある一般的な問題のみを解決することができます。このセクションでは、メインのガベージコレクションアルゴリズムとその制限を理解するために必要な概念について説明します。
引用
ごみ収集アルゴリズムは、主に参照の概念に依存しています。メモリ管理された環境では、オブジェクトが別のオブジェクトにアクセスする許可を持つ場合(暗黙的または明示的に)、別のオブジェクトを参照するオブジェクトと呼ばれます。たとえば、JavaScriptオブジェクトには、そのプロトタイプ(暗黙的な参照)への参照とそのプロパティへの参照(明示的な参照)があります。
ここでは、「オブジェクト」の概念は、特別なJavaScriptオブジェクトだけでなく、関数範囲(またはグローバルな語彙スコープ)もあります。
参照カウントガベージコレクション
これは、最も簡単なゴミコレクションアルゴリズムです。このアルゴリズムは、「オブジェクトがもはや必要でないかどうか」を「オブジェクトに参照する他のオブジェクトを持っているかどうか」として簡素化されます。オブジェクト(ゼロ参照)を参照しない場合、オブジェクトはガベージコレクションメカニズムによってリサイクルされます。
例えば
コードコピーは次のとおりです。
var o = {
A:{
B:2
}
};
// 2つのオブジェクトが作成され、1つは他の属性として参照され、もう1つは変数oに割り当てられます
//明らかに、それらのどれもごみで収集することはできません
var o2 = o; // o2変数は「このオブジェクト」への2番目の参照です
o = 1; //「このオブジェクト」の元の参照oはo2に置き換えられます
var oa = o2.a; //「このオブジェクト」のプロパティを参照してください
//今、「このオブジェクト」には2つの参照があります。1つはO2、もう1つはOAです
o2 = "yo"; //元のオブジェクトはゼロ参照になります
//彼はリサイクルできます
//ただし、そのプロパティAのオブジェクトはまだOAによって参照されるため、まだリサイクルできません
oa = null;
//ゴミ収集される可能性があります
制限:リサイクルリファレンス
この単純なアルゴリズムには、オブジェクトが別のものを参照する場合(円形の参照を形成する)、「もはやそれを必要としない」が、リサイクルされないという制限があります。
コードコピーは次のとおりです。
関数f(){
var o = {};
var o2 = {};
OA = O2; //参照O2
o2.a = o; // o2引用o
「azerty」を返します。
}
f();
// 2つのオブジェクトが作成され、互いに参照され、ループを形成します
//呼び出された後、彼らは関数の範囲を離れません
//したがって、それらは役に立たず、リサイクルできます
//ただし、参照カウントアルゴリズムでは、少なくとも一度は相互に参照があるため、リサイクルされないことを考慮しています。
実用的な例
IE 6、7 DOMオブジェクトのカウントのリサイクル。彼らにとって一般的な問題は、メモリリークです:
コードコピーは次のとおりです。
var div = document.createelement( "div");
div.onclick = function(){
dosomething();
};
// divにはイベントの処理プロパティを指す参照がありますonclick
//イベントハンドリングには、関数スコープでアクセスできるDIVへの参照もあります
//この円形の参照により、両方のオブジェクトが集められます
マーククリアリングアルゴリズム
このアルゴリズムは、「オブジェクトが使用可能かどうか」として「オブジェクトが不要になったかどうか」を簡素化します。
このアルゴリズムは、ルートと呼ばれるオブジェクトの設定を想定しています(JavaScriptでは、ルートはグローバルオブジェクトです)。定期的に、ガベージコレクターはルートで開始し、ルートから参照されるすべてのオブジェクトを見つけてから、これらのオブジェクトによって参照されるオブジェクトを見つけます...ルートから始まると、ガベージコレクターは取得できるすべてのオブジェクトと取得できないすべてのオブジェクトを見つけます。
このアルゴリズムは以前のアルゴリズムよりも優れています。これは、「参照を持つオブジェクト」は常に利用できないためですが、それどころか、「循環参照」を参照することは必ずしも真実ではありません。
2012年以来、すべての最新のブラウザはタグクリーンガベージコレクションアルゴリズムを使用しています。 JavaScript Garbage Collection Algorithmのすべての改善は、タグクリーニングアルゴリズム自体を改善することなく、オブジェクトが不要かどうかの簡素化された定義を改善することなく、タグクリーニングアルゴリズムの改善に基づいています。
循環参照はもはや問題ではありません
上記の例では、関数呼び出しが返された後、両方のオブジェクトをグローバルオブジェクトから取得することはできません。したがって、それらはゴミコレクターによってリサイクルされます。
2番目の例は、divとそのイベント処理をルートから取得できなくなると、ガベージコレクターによってリサイクルされます。
制限:オブジェクトは明示的に利用できない必要があります
これは制限ですが、それはめったに破られません。そのため、実際にはゴミ収集メカニズムに関心がある人はほとんどいません。