主人公を率いる
まず、グローバル変数、システムがページを閉じたときに占有されていたメモリ、関数ローカル変数が解放され、関数が実行されたときにメモリが解放されることを思い出してください。今日の主役はJs ガベージコレクションメカニズムです。
このプロセスを処理するために必要なすべての言語。たとえば、C言語では、メモリを手動で適用して解放する必要があります。
また、 Javascriptは自動的にメモリ管理を支援し、メモリ管理ライフサイクル全体を完了し、開発者がビジネスロジック自体に集中できるようにします。
しかし同時に、それはまた、開発者にとってメモリ管理の幻想を生み出しました。
このプロセスを要約します。
- 必要なメモリを割り当てます
- 割り当てられたメモリを使用する(読み取り、書き込み)
- 必要のない場合は解放\返却
ガベージコレクションの2つの重要なポイントを次に示します。
- メモリーリーク
何らかの理由でメモリが不要になった場合、解放できません。これは、原因となる メモリリークが 崩壊するまで、占有されているプログラムメモリを引き起こし、。
- アクセシビリティ
ガベージコレクションの標準は、オブジェクトが到達可能かどうか、および変数を参照できるかどうかです。
見積もり
オブジェクト{name:xxx}のメモリアドレスは、変数aおよびbによって2回参照されます。aにnullの値が割り当てられると、bはまだ参照されており到達可能であるため、再利用されません。
var a = { name: "小红"};
var b = a;
a.name = "小黑";
console.log(b)
a = null;
console.log(b)
b = null;
ときにtest1()
実行され、システムはOBJのためにメモリを割り当て、機能が実行されたとき、メモリが再利用されます。
場合test2()
OBJが実行され、メモリは開放されているが、OBJは、グローバル変数になる返された結果によって、Bに割り当てられ、破壊されないであろう
function test1 () {
var obj = {}
}
function test2 () {
var obj = {}
return obj
}
const a = func1()
const b = func2()
一般的に使用されるガベージコレクションの2つの方法を紹介します。
1.参照の削除(IE9より前に採用)
宣言後に変数が参照される回数。0の場合、変数メモリは破棄されます
function test () {
var a = {} // a的引用计数为 0,
var b = a // a 被 b 引用 a引用计数为 1
let c = a // a 被 c 引用 a引用计数为 2
b = null // b 不再引用a a的引用计数减为 1
c = null // c不再引用a a的引用计数减为 0 被回收
}
利点
- ガベージをすぐに収集し、参照された値が0の場合、すぐに収集されます
- ヒープ内のすべてのアクティブおよび非アクティブなオブジェクトをトラバースする必要はありません
不利益
- 見積りの上限を見積もることができないため、カウンターは大きなスペースを占める必要があります
- 最大の欠点は、循環参照をリサイクルできないという問題を解決できないことです。
function problem(){
var a = new Object();
var b = new Object();
a.test = b;
b.test = a;
}
上記のaとbはお互いを参照しており、カウントは0になりません。メモリはリサイクルされません。繰り返しの呼び出しは大量のメモリを占有します
2. V8エンジンの内部(基本的に現在採用されており、マークはクリアされています)
これは、ブラウザのJavascript
解析エンジンV8 で採用されています。マーキングステージ:すべてのアクティブなオブジェクトをマークし、マークされていないオブジェクト(つまり、非アクティブなオブジェクト)を破棄します。
グローバルスコープ内の変数から、スコープに沿ってレイヤーごとに深さ方向に移動します。参照が見つかった場合は、マークを付け、実行が完了した後、マークされていない変数メモリは破棄されます。
一般的なメモリリークについて話す
Fooが呼び出されると、これはグローバル変数(ウィンドウ)を指します。これはグローバル変数と同等であり、変数はリサイクルされません
function test() {
this.test = "lala";
}
foo();
ノードが強制終了されると、タイマーは引き続き実行されます
setInterval(function() {
var node = document.getElementById('div');
if(node) {
node.innerHTML = "!。。。。。。。"
}
}, 5000);
閉鎖
カウンター
グローバル環境を汚染することなくインクリメントを達成します。子関数は親関数変数numを参照し、numは親関数の実行後にリサイクルされません。子関数が実行されると、一番外側のグローバル環境変数addに戻り、ステータスを記録します。これは実際にはメモリですリークケース
var add = (function () {
var num = 0;
return function () {
return ++num;
};
})();
console.log(add());
console.log(add());
console.log(add());
メモリ管理をオフにする
- 通常、スタックストレージ(基本タイプの値)はリークせず、ヒープストレージ(参照タイプの値はオブジェクト)がリークします
- 一般的に、小さなメモリリークはプログラムに影響を与えませんが、大規模なプロジェクトの場合は、蓄積が少なすぎないようにし、適切なプログラミングの習慣を身につけます