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

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

WBOY
リリース: 2016-05-16 17:26:24
オリジナル
934 人が閲覧しました

はじめに
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
}; // 属性値を含むオブジェクトの場合メモリを割り当てる
var a = [1, null, "abra"] // 値を含む配列にメモリを割り当てます
function f(a){
return a 2;
} // for Functions はメモリを割り当てます (関数は呼び出し可能なオブジェクトです)
// 関数式もオブジェクトであり、メモリを割り当てる場合もあります
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); // を入れます。と a2 を組み合わせて新しい配列

を生成します
値の使用
値を使用すると、実際には、割り当てられたメモリに対して読み取りおよび書き込み操作が実行されます。これらの操作には、変数またはオブジェクト プロパティに対する読み取りおよび書き込み操作、または関数へのパラメーターの受け渡しが含まれます。
メモリが不要になったら解放します
メモリ管理の問題のほとんどはこの段階で発生します。最も難しいのは、割り当てられたメモリがいつ不要になるかを判断する方法です。このため、開発者は多くの場合、プログラムがメモリを必要としなくなった時期を判断し、メモリが占​​有しているリソースを解放する必要があります。
「ガベージ コレクター」と呼ばれるプログラムは、高級言語パーサーに組み込まれており、メモリの割り当てと使用状況を追跡し、メモリが必要かどうかを判断し、メモリが不要になった場合はリソースの解放操作を実行します。必要です。メモリが必要かどうかの判断は不確実な問題である (アルゴリズムでは解決できない) ため、彼は近似値を取得することしかできません。
ガベージコレクション
前述したように、「メモリが不要になった」ことを正確かつ自動的に判断することはできません。したがって、この問題の解決策としてガベージ コレクションには限界があります。このセクションでは、主要なガベージ コレクション アルゴリズムとその制限事項を理解するために必要な概念について説明します。
参照
ガベージ コレクションの主な概念の 1 つは参照です。メモリ管理では、オブジェクトが明示的または暗黙的に別のオブジェクトを使用することを、そのオブジェクトが別のオブジェクトを参照すると言います。たとえば、JavaScript オブジェクトには、そのプロトタイプへの暗黙的な参照と、そのプロパティ値への明示的な参照があります。
ここでのオブジェクトの概念は、JavaScript における従来のオブジェクトの概念を超えており、関数スコープとグローバル スコープも含まれています。
参照カウントアルゴリズムを用いたガベージコレクション
以下で紹介するのは、「オブジェクトが不要になる」「他のオブジェクトがそのオブジェクトを参照しない」という概念を導入した最適なアルゴリズムです。オブジェクトの参照ポインタが 0 になると、リサイクルの準備ができたとみなされます。
例:
コードをコピー コードは次のとおりです。

var o = {
a: {
b:2
}
}; // 2 つのオブジェクトが作成され、1 つのオブジェクト (a) が別のオブジェクト (o で参照されるオブジェクト) によって参照され、a が使用されます。その属性
// オブジェクトは変数 o によって再び参照されます
// 明らかに、現時点ではオブジェクトをリサイクルできません
var o2 = o; // 変数 o2 はオブジェクトを再度参照します
o = 1 ; // o はオブジェクトを参照しなくなり、o2 のみが引き続きオブジェクトを参照します
var oa = o2.a; // oa は o2 の属性オブジェクトを参照します
// このオブジェクトは他の 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
return "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 とイベント ハンドラーがガベージ コレクターによってアクセス不能としてマークされると、それらは解放されます。
制限事項: オブジェクトは明示的にアクセス不能としてマークする必要があります
このマーク付け方法には制限がありますが、プログラミングでは制限にさらされることはないため、ガベージ コレクション関連のコンテンツを気にすることはほとんどありません。
関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート