ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScriptのメモリ管理を詳しく分析_基礎知識

JavaScriptのメモリ管理を詳しく分析_基礎知識

WBOY
WBOYオリジナル
2016-05-16 17:16:30965ブラウズ

はじめに

C などの低レベル言語には、malloc() や free() などの低レベルのメモリ管理コマンドがあり、開発者は手動でメモリを解放する必要があります。ただし、JavaScript などの高級言語では状況が異なります。オブジェクト (オブジェクト、文字列など) は作成時にメモリを割り当て、使用されなくなったメモリは自動的にリサイクルされます。この自動リサイクルプロセスはガベージコレクションと呼ばれます。 JavaScript などの高級言語の開発者は、ガベージ コレクションの存在により、メモリ管理を気にする必要がないと誤解しています。

メモリのライフサイクル

どのようなプログラミング言語であっても、メモリのライフサイクルは基本的に同じです。

1. 必要なメモリを割り当てます

2. 読み取りおよび書き込み操作に使用します

3. メモリが不要になったらリソースを解放します

ステップ 1 と 2 はすべての言語で同じであり、明確に気づくことができます。ステップ 3 に関しては、低レベル言語では開発者がこれを明示的に実行する必要があります。 JavaScript のような高水準言語の場合、操作のこの部分はパーサーによって実行されるため、気付かれることはありません。

JavaScript での代入操作

値の初期化

変数に値を代入すると、JavaScript によってメモリの割り当てが完了します。

コードをコピーします コードは次のとおりです。

var n = 123; // メモリを割り当てます。数値の場合
var s = "azerty"; // 文字列にメモリを割り当てます

var o = {
a: 1,
b: null
}; // 属性を含みますvalue オブジェクト object はメモリを割り当てます

var a = [1, null, "abra"] // 値を含む配列にメモリを割り当てます

function f(a){
; return a 2;
} // 関数にメモリを割り当てます (関数は呼び出し可能なオブジェクトです)

// 関数式もオブジェクトであり、メモリを割り当てる場合があります
someElement。 addEventListener('click' , function(){
someElement.style.backgroundColor = 'blue';
}, false);

関数呼び出しにより割り当てが完了しました

いくつかの関数が実行された後、オブジェクトの割り当ても行われます。

コードをコピー コードは次のとおりです。

var d = new Date();
var e = document.createElement('div'); // DOM 要素を割り当てます

一部のメソッドは新しい値またはオブジェクトを割り当てます。
コードをコピー コードは次のとおりです。

var s = "azerty";
var s2 = s.substr(0, 3); // s2 は新しい文字列です
// 文字列は変更されていないため、JavaScript は範囲 [0, 3]
var a = ["ouais ouais", "nan nan"];
var a2 = ["世代", "nan nan"];
var a3 = a.concat(a2) / / a と a2 を組み合わせて新しい配列を生成します


値の使用

値の使用は、実際には、割り当てられたメモリ上で読み取りおよび書き込み操作を実行することです。これらの操作には、変数またはオブジェクト プロパティに対する読み取りおよび書き込み操作、または関数へのパラメーターの受け渡しが含まれます。

不要になったらメモリを解放します

メモリ管理の問題のほとんどはこの段階で発生します。最も難しいのは、割り当てられたメモリがいつ不要になるかを判断する方法です。このため、開発者は多くの場合、プログラムがメモリを必要としなくなった時期を判断し、メモリが占​​有しているリソースを解放する必要があります。

「ガベージ コレクター」と呼ばれるプログラムは、高級言語パーサーに組み込まれており、メモリの割り当てと使用状況を追跡し、メモリが必要かどうかを判断し、メモリが不要になった場合はリソースの解放操作を実行します。必要です。メモリが必要かどうかの判断は不確実な問題である (アルゴリズムでは解決できない) ため、彼は近似値を取得することしかできません。

ガベージコレクション

上で述べたように、「メモリが不要になった」と正確かつ自動的に判断することはできません。したがって、この問題の解決策としてガベージ コレクションには限界があります。このセクションでは、主要なガベージ コレクション アルゴリズムとその制限事項を理解するために必要な概念について説明します。

引用

ガベージ コレクションの主要な概念は参照です。メモリ管理では、オブジェクトが明示的または暗黙的に別のオブジェクトを使用することを、そのオブジェクトが別のオブジェクトを参照すると言います。たとえば、JavaScript オブジェクトには、そのプロトタイプへの暗黙的な参照と、そのプロパティ値への明示的な参照があります。

ここでのオブジェクトの概念は、JavaScript における従来のオブジェクトの概念を超えており、関数スコープとグローバル スコープも含まれています。

参照カウント アルゴリズムを使用したガベージ コレクション

以下に紹介するのは、「オブジェクトが不要になった」、「他のオブジェクトがそのオブジェクトを参照しない」という概念を導入した最適なアルゴリズムです。オブジェクトの参照ポインタが 0 になると、リサイクルの準備ができたとみなされます。

例:

コードをコピー コードは次のとおりです。

var o = {
a: {
b:2
}
}; // 2 つのオブジェクトが作成され、1 つのオブジェクト (a) が別のオブジェクト (o で参照されるオブジェクト) によって参照されます。その属性
// オブジェクトは変数 o によって再び参照されます
// 明らかに、現時点ではオブジェクトをリサイクルできません


var o2 = o; // 変数 o2 は、再びオブジェクト
o = 1; // o はオブジェクトを参照しなくなり、o2 のみが引き続きオブジェクトを参照します

var oa = o2.a; // oa は o2 の属性オブジェクト a を参照します
// このオブジェクトは、他の 2 つのオブジェクト、つまり o2 の属性 a と oa 変数によって参照されています。

o2 = "yo"; // このオブジェクトは他のオブジェクトから参照されなくなりました。属性 a はまだ oa 変数によって参照されているため、まだ解放できません

oa = null; // これで属性 a は他のオブジェクトから参照されなくなり、オブジェクトはリサイクルできるようになります


制限: ループ

このアルゴリズムには制限があります。オブジェクトが別のオブジェクトを参照し、循環参照が形成されると、それらが不要になった場合でも、ガベージ コレクターはそれらを再利用しません。

コードをコピー コードは次のとおりです。

function f(){
var o = { };
var o2 = {};
o.a = o2; // o2 は o2
を参照します。 o2.a = o; // o2 は o

を参照します。 azerty";
}

f();
// 2 つのオブジェクトが作成され、相互参照を形成します
// 関数呼び出しが終了した後、それらは関数スコープから出ません。使用されませんが、解放されません
// これは、オブジェクトが参照されている限り、ガベージ コレクションを実行できないと参照カウント アルゴリズムが判断するためです

現実
ie6 および 7 の例では、DOM オブジェクトに対して参照カウント アルゴリズムが使用されており、メモリ リークの問題が発生します。

コードをコピー コードは次のとおりです。

var div = document.createElement("div ");
div.onclick = function(){
doSomething();
}; // div は click 属性を通じてイベント ハンドラーを参照します
// div 変数がアクセスされたときイベント ハンドラー関数は循環参照を形成し、両方のオブジェクトがリサイクルされなくなり、メモリ リークが発生します

タグ - アルゴリズムのクリア

彼は、「不要になったオブジェクト」と「到達不能なオブジェクト(オブジェクト到達不能)」という概念を導入しました。このアルゴリズムは、一連のルート オブジェクトが存在することを前提としています (JavaScript のルート オブジェクトはグローバル オブジェクトです)。ガベージ コレクターはルート オブジェクトから開始し、参照するすべてのオブジェクトを走査し、次に、ルート オブジェクトを走査します。参照オブジェクトによって参照されるオブジェクトなど。このアプローチを使用すると、ガベージ コレクターはアクセス可能なすべてのオブジェクトを取得し、アクセスできないオブジェクトを再利用できます。

このアルゴリズムは、0 によって参照されるオブジェクトがアクセス不可能なオブジェクトとして設定されると同時に、循環参照によって引き起こされる問題も回避します。

2012 年現在、ほとんどの最新ブラウザはこの「マーク アンド スイープ」ガベージ コレクターを使用しています。 JavaScript のガベージ コレクション (世代別/増分/同時/並列ガベージ コレクション) の分野は、ここ数年でそれに関連するアルゴリズムが改良されてきましたが、ガベージ コレクションのアルゴリズムそのもの (マークスイープ アルゴリズム) や「オブジェクトかどうかを判断する方法」は、はもう必要ありません」は改善されていません。

生理周期はもう問題ではありません

最初の例では、関数呼び出しが終了すると、これら 2 つのオブジェクトはグローバル オブジェクトによって参照されなくなり、グローバル オブジェクトによって参照されるオブジェクトからも参照されなくなります。したがって、これらは JavaScript ガベージ コレクターによってアクセス不可能なオブジェクトとしてマークされます。 2 番目の例でも同じことが起こり、div とイベント ハンドラーがガベージ コレクターによってアクセス不能としてマークされると、それらは解放されます。

制限事項: オブジェクトは明示的にアクセス不可としてマークする必要があります

このマーキング方法には制限がありますが、プログラミングでこの方法に触れたことがないため、ガベージ コレクション関連のコンテンツについてはほとんど気にしません。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。