什么是內存泄露?
已經不再使用的內存未能被程序釋放,叫內存泄露(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 即可。
事件監聽導致的內存泄露,監聽后移除即可。