前端內存泄漏檢查判斷及處理


什么是內存泄露?

已經不再使用的內存未能被程序釋放,叫內存泄露(memory leak)。

內存泄露會帶來什么樣的后果?

內存泄露會因為減少可用內存數量從而降低計算機性能,嚴重的可能導致設備停止正常工作,或者應用程序崩潰。

什么情況下出現內存泄漏?

首先了解一下垃圾回收:垃圾回收(英語:Garbage Collection,縮寫為GC)在計算器科學中是一種自動的存儲器管理機制。當一個計算機上的動態存儲器不再需要時,就應該予以釋放,以讓出存儲器,這種存儲器資源管理,稱為垃圾回收。

當一塊內存不再用到,但是垃圾回收機制又無法釋放這塊內存的時候,就導致內存泄漏。

出現內存泄露的的幾種常見情況:

1、全局變量

由於JavaScript對未聲明變量的處理方式是在全局對象上創建該變量的引用。如果在瀏覽器中,全局對象就是window對象。
變量在窗口關閉或重新刷新頁面之前都不會被釋放,如果未聲明的變量緩存大量的數據,就會導致內存泄露。

(1). 未聲明變量:
     a = '我是未聲明的變量a,我緩存了數據,如果數據足夠大的話,就會內存泄漏'

(2). 通過this也會創建全局變量,當在全局作用域中調用一個函數,這個函數內部用this.var的方式創建了一個變量,
此時this指向的是全局對象(window),而不是'undefined'如:

    function leak() {
      this.variable = "potential accidental global"
    }
    leak()

2、閉包(closures): js函數內可以直接讀取全局變量,但是函數外不能讀取函數內的局部變量。這時候在函數f1內再聲明一個函數f2調用局部變量,

      然后返回函數f2,在f1的外部聲明一個變量result賦值為f1,再調用result,就是一個閉包的例子。

    function f1(){
    var n = 999;
    function f2(){
      alert(n); 
    }
    return f2;
  }

  var result = f1();
  result(); // 999
    
    閉包可以讀取函數內部的變量,然后讓這些變量始終保存在內存中。如果在使用結束后沒有將局部變量清除,就可能導致內存泄露。

3、事件監聽(EventListener)
   對同一個事件重復監聽,但是忘記移除,會導致內存泄露。

4、其他原因
   console.log打印的對象不能被垃圾回收,可能會導致內存泄露。
   setInterval也可能會導致內存泄露。

前端如何檢查內存泄露?

(1).使用Chrome的開發者工具profiles來進行快照對比。

(2).如果是在Node環境下,可以用Node提供的process.memoryUsage()方法來檢查內存泄露:

rss (resident set size) : 所有內存占用,包括指令區和堆棧。

heapTotal : "堆"占用的內存,包括用到的和未用到的。

heapUsed : 用到的堆。

external : V8引擎內部C++對象占用的內存。

判斷內存泄露以heapUsed為准。

 

如何處理內存泄漏?

變量導致的內存泄露,將變量清除 a = null 即可。

事件監聽導致的內存泄露,監聽后移除即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM