前端的學習已經進入了一個艱難的上升期,越來越發現自己學習的東西還多得多,需要掌握的知識面寬廣了很多,知識點需要理解的深度也加深了很多。今天看到前端內存泄漏相關,自己總結總結,也便于自己以后學習記憶。由于經驗所致,必然會有不足之處,歡迎指正!
什么是內存
內存是計算機中重要的部件之一,它是與CPU進行溝通的橋梁。計算機中所有程序的運行都是在內存中進行的,因此內存的性能對計算機的影響非常大。
什么是內存泄漏
內存泄漏(Memory Leak)是指程序中己動態分配的堆內存由于某種原因程序未釋放或無法釋放,造成系統內存的浪費,導致程序運行速度減慢甚至系統崩潰等嚴重后果。 說白了就是 不再用到的內存,沒有及時釋放,就叫做內存泄漏(memory leak)。
看完上面的解釋,腦海中就會有一點概念,計算機正常運轉會用到內存,內存像是一個中轉站,他把你暫存的數據,馬上就會用到的數據存儲在這,以讓你更快捷方便的使用, 那你肯定會想到一個問題,暫存的數據到底哪些該存儲在這里,存儲的東西不會一直在這,又是怎么消失的呢?
在我的理解,前端開發中,全局的、被引用的對象就會被保存在內存中。比如我們常見的閉包:
function leak(arg) {
this.arg = arg;
}
function test() {
var l1= new leak('It is a leak');
document.body.addEventListener('click', function() {
l1.arg = 'Here you are!'
})
}
test()
很明顯,l1被閉包環境引用,無法被回收
那么瀏覽器是怎么判斷一個對象是不是該被垃圾回收了呢
對前端開發來說只需要理解'引用計數法'就可以了 語言引擎有一張"引用表",保存了內存里面所有的資源(通常是各種值)的引用次數。如果一個值的引用次數是0,就表示這個值不再用到了,因此可以將這塊內存釋放。
代碼層面內存泄露的原因
- 循環引用
- 閉包
- 全局變量
- 沒有清理的DOM元素引用
- 被遺忘的定時器以及其中的引用
可能造成了內存泄漏要怎么排查
- 我們可以使用chrome瀏覽器調試工具中的內存快照,點擊左上角灰色原點就可以保存一份快照,記錄此時內存使用情況 可以看到代碼中明顯的l1對象被引用導致無法釋放,在快照中我們也看到了一個leak實例在內存中。通過見=簡單分析就可以知道是哪塊代碼出了問題


2. 如果是在Node環境下,可以用Node提供的process.memoryUsage()方法來檢查內存泄露:具體方法可以參考阮一峰的例子:https://github.com/ruanyf/es6tutorial/issues/362#issuecomment-292451925
- rss (resident set size) : 所有內存占用,包括指令區和堆棧。
- heapTotal : "堆"占用的內存,包括用到的和未用到的。
- heapUsed : 用到的堆。
- external : V8引擎內部C++對象占用的內存。
判斷內存泄露以heapUsed為準。
如何處理
- 避免循環引用等發生源
- 變量導致的內存泄露,將變量清除 a = null
- 事件監聽導致的內存泄露,監聽后移除
作者:天微蔚藍
鏈接:https://juejin.im/post/5c6663a85188252a160efa3c
來源:掘金