JavaScript 的垃圾收集機制
javascript具有自動垃圾收集機制,也就是說,執行環境會負責管理代碼執行過程中的使用的內存。而在C和C++之類的語言中,開發人員的一項基本任務就是手動跟蹤內存的使用情況,這是造成許多問題的一個根源。在編寫javascript程序時候,開發人員不用再關心內存使用的問題,所需內存的分配 以及無用的回收完全實現了自動管理。
JavaScript中最常用的垃圾收集方式是標記清除(mark-and-sweep)。當變量進入環境(例如,在函數中聲明一個變量)時,就將這個變量標記為“進入環境”。從邏輯上講,永遠不能釋放進入環境的變量所占的內存,因為只要執行流進入相應的環境,就可能用到它們。而當變量離開環境時,這將其 標記為“離開環境”。
常見內存泄漏的原因
雖然JavaScript 會自動垃圾收集,但是如果我們的代碼寫法不當,會讓變量一直處於“進入環境”的狀態,無法被回收。下面列一下內存泄露常見的幾種情況。
全局變量引起的內存泄漏
function leaks(){ leak = 'xxxxxx';//leak 成為一個全局變量,不會被回收 }
123
閉包引起的內存泄漏
var leaks = (function(){ var leak = 'xxxxxx';// 被閉包所引用,不會被回收 return function(){ console.log(leak); } })()
123456
dom清空或刪除時,事件未清除導致的內存泄漏
<div id="container"> </div> $('#container').bind('click', function(){ console.log('click'); }).remove(); // zepto 和原生 js下,#container dom 元素,還在內存里jquery 的 empty和 remove會幫助開發者避免這個問題
12345678
<div id="container"> </div> $('#container').bind('click', function(){ console.log('click'); }).off('click').remove(); //把事件清除了,即可從內存中移除
1234567
關於這個問題,更詳細的內容可以參考我的另外一篇文章關於 dom清空的內存泄漏問題
子元素存在引用引起的內存泄漏
- 黃色是指直接被 js變量所引用,在內存里
- 紅色是指間接被 js變量所引用,如上圖,refB 被 refA 間接引用,導致即使 refB 變量被清空,也是不會被回收的
- 子元素 refB 由於 parentNode 的間接引用,只要它不被刪除,它所有的父元素(圖中紅色部分)都不會被刪除