javascript垃圾回收機制

(一)Javascript中垃圾回收主要針對以下兩種情況:
1. 在javascript中,如果一個對象不再被引用,那麼這個對象就會被GC回收;
2. 如果兩個對象互相引用,而不再被第3者所引用,那麼這兩個互相引用的對象也會被回收。

(二)Javascript垃圾回收的方法主要有兩種:
3. 標記清除(mark and sweep)
這是JavaScript最常見的垃圾回收方式,當變量進入執行環境的時候,比如函數中聲明一個變量,垃圾回收器將其標記爲“進入環境”,當變量離開環境的時候(函數執行結束)將其標記爲“離開環境”。
垃圾回收器會在運行的時候給存儲在內存中的所有變量加上標記,然後去掉環境中的變量以及被環境中變量所引用的變量(閉包),在這些完成之後仍存在標記的就是要刪除的變量了。
例如:

function test(){
 var a = 10 ; //被標記 ,進入環境 
 var b = 20 ; //被標記 ,進入環境
}
test(); //執行完畢 之後 a、b又被標離開環境,被回收。

 到目前爲止,IE、Firefox、Opera、Chrome、Safari的js實現使用的都是標記清除的垃圾回收策略或類似的策略,只不過垃圾收集的時間間隔互不相同。
 
2. 引用計數(reference counting)
在低版本IE中經常會出現內存泄露,很多時候就是因爲其採用引用計數方式進行垃圾回收。引用計數的策略是跟蹤記錄每個值被使用的次數,當聲明瞭一個 變量並將一個引用類型賦值給該變量的時候這個值的引用次數就加1,如果該變量的值變成了另外一個,則這個值得引用次數減1,當這個值的引用次數變爲0的時候,說明沒有變量在使用,這個值沒法被訪問了,因此可以將其佔用的空間回收,這樣垃圾回收器會在運行的時候清理掉引用次數爲0的值佔用的空間。
例如:

function test(){
 var a = {} ; //a的引用次數爲0 
 var b = a ; //a的引用次數加1,爲1 
 var c =a; //a的引用次數再加1,爲2
 var b ={}; //a的引用次數減1,爲1
}

在IE中雖然JavaScript對象通過標記清除的方式進行垃圾回收,但BOM與DOM對象卻是通過引用計數回收垃圾的, 也就是說只要涉及BOM及DOM就會出現循環引用問題。

(三)內存泄漏
內存泄漏指任何對象在您不再擁有或需要它之後仍然存在。
會引發內存泄露的情況主要有:setTimeout 的第一個參數使用字符串而非函數的話,會引發內存泄漏。閉包、控制檯日誌、循環(在兩個對象彼此引用且彼此保留時,就會產生一個循環),內存泄漏導致垃圾無法回收,影響性能。
下面以閉包導致內存泄漏的問題爲例:

window.onload = function(){
    var el = document.getElementById("id");
    el.onclick = function(){
        alert(el.id);
    }
}

這段代碼會導致內存泄漏,因爲匿名函數對象賦值給e1的onclick事件,然後匿名函數內部又引用了e1對象,存在循環引用,所以不能被回收。
解決方法:
將閉包引用的外部函數中活動對象置爲空,就可以被垃圾回收機制回收。

window.onload = function(){
    var el = document.getElementById("id");
    var id = el.id; //解除循環引用
    el.onclick = function(){
        alert(id); 
    }
    el = null; //將閉包引用的外部函數中活動對象置爲空}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章