1.ブラウザのメモリリーク
ブラウザによってカプセル化されたV8エンジンは、JSの解析をサポートします。プログラムの実行中(ランタイム)、割り当てられた文字列、オブジェクト、配列などの変数を宣言するときなど、プログラムがメモリを必要とする限り、オペレーティングシステムは使用するメモリを割り当てる必要があります。実行中のサービスプロセスの変数は絶えず増加しており、メモリが時間内に解放されない場合、メモリの占有率がますます大きくなり、システムのパフォーマンスに影響を与えたり、システムを直接クラッシュさせたりします。
1.閉鎖と参照
let fn = () =>{
let a = 0
return () => {
return a++
}
}
let b = fn()
console.log(b()) // 0
console.log(b()) // 1
閉鎖はIE6でメモリリークを引き起こす可能性がありますが、それらはもはや考慮されていません。変数aは再利用できませんが(グローバル変数と同等)、このメモリについて特別な考慮事項はありません。クロージャ自体はメモリリークを引き起こしませんが、クロージャが多すぎるとメモリリークが発生しやすくなることに注意してください。
2.相互参照
let aa = {
}
let bb = {
}
aa.c = bb
bb.c = aa
解決策:変数を参照しないでください
3.グローバルな宣言されていない変数
function fn1() {
aa = 1 // window.aa
console.log(aa)
}
fn2()
function fn2() {
this.bb = 1 // window.bb
console.log(bb)
}
fn2()
関数fn1およびfn2は宣言されていません。つまり、変数はグローバルオブジェクトウィンドウにバインドされているため、関数の実行後に変数メモリを解放することはできません。
解決策:strictモードを使用し、jsの先頭に「usestrict」を追加します
4.タイマーとコールバック機能
let a = 2
setInterval(() =>{
console.log(a++)
}, 1000)
setIntervalまたはsetTimeoutが不要な場合、タイマーはクリアされず、タイマーのコールバック関数と内部従属変数を再利用できないため、メモリリークが発生します。
5.DOMオブジェクトに属性を追加します
document.getElementById('id')[property] = obj
DOMが存在する場合、常にこのイベントをバインドします。解決策は次のとおりです。
window.onunload = function(){
document.getElementById('id')[property] = null
}
7. vueのタイマー、イベントモニタリング、$ onなど
解決策:beforeDestroyフックの関連イベントを削除または閉じます
2、ゴミ収集メカニズム
変数のライフサイクル:変数のライフサイクルが終了すると、変数が指すメモリが解放されます。JSには、グローバル変数と関数で生成されたローカル変数(参照変数を除く)の2種類の変数があります。ローカル変数のライフサイクルは、関数の実行後に終了し、それが参照するメモリを解放(つまり、ガベージコレクション)できますが、グローバル変数のライフサイクルは、ブラウザがページを閉じるまで続きます。ガベージコレクターは、使用されなくなった変数を検出し、それらが占有していたメモリを解放し、一定の時間間隔で定期的に実行します。
最新のブラウザには、マークの削除と参照のカウントという2つの主要なタイプのガベージコレクションメカニズムがあります。
1.マークアンドスイープ
現在の主流のIE、Firefox、Opera、Chrome、およびSafariブラウザーはすべて、マークアンドスイープガベージコレクション戦略を使用しています。
仕組み:変数が環境に入ると、その変数は「環境に入る」とマークされます。変数が環境を離れると、「環境外」としてマークされます。「環境を離れる」とマークされたメモリが再利用されます。
ワークフロー:
1。ガベージコレクターは、実行時にメモリに保存されているすべての変数にマークを付けます。
2.環境内の変数によって参照されるグローバル変数と変数のタグを削除します。
3.マークされたものは、削除される変数と見なされます。
4.ガベージコレクターはメモリのクリーンアップを完了し、マークされた値を破棄し、それらが占有しているメモリスペースを再利用します。
2.参照カウント(参照カウント)参照カウント
の意味は、各値が参照された回数を追跡および記録することです。変数が宣言され、参照タイプの値が変数に割り当てられている場合、この値への参照の数は1です。同じ値が別の変数に割り当てられている場合、値への参照の数は1増加します。逆に、この値への参照を含む変数が別の値を取得すると、この値への参照の数は1つ減ります。この値への参照の数が0の場合、この値にアクセスする方法がなくなったことを意味します。占有していたメモリスペースを再利用します。
let aa = [] // 数组[]引用1次
let bb = aa // 数组引用2次
bb = null // 释放内存,引用还剩下1次,即变量aa的引用还存在
このような単純なガベージコレクションメカニズムは、循環参照の問題を非常に起こしやすく、メモリがリサイクルされず、メモリリークが発生する可能性があります。例:
let aa = {}
let bb = {}
aa.c = bb
bb.c = aa
var wraper = document.querySelector('#btn');
wraper.onclick = handle;
wraper = null;
wraper = null;
このメソッドは、ラッパーによって参照される変数が解放され、実際のオブジェクトDOMがすでにbtnクリックイベントをバインドしているため、domクリックイベントを解放できません。
let a = {
}
let b = a
b.btn = () =>{
}
b = null
console.log(a)