JSガベージコレクションメカニズムとメモリリーク

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)

おすすめ

転載: blog.csdn.net/zxlong020/article/details/108566610