JS中的垃圾回收機制


必要性:由於字符串、對象和數組沒有固定大小,所有當他們的大小以知時,才能對他們進行動態的存儲分配。JavaScript程度每次創建字符串、數組或對象時,解釋器都必須分配內存來存儲那個實體。只要像這樣動態地分配了內存,最終都要釋放這些內存以便他們能夠被再用,否則,javascript的解釋器將會消耗完系統中所有可用的內存,造成系統崩潰。

這段話解釋了為什么需要系統需要垃圾回收,JS不像C/C++,他有自己的一套垃圾回收機制。javascript的解析器可以檢測到何時程序不再使用一個對象了,當他確定了一個對象是無用的時候,他就知道不再需要這個對象,可以把它所占用的內存釋放掉了。

例如:

   

var a="hello world";
var b="world";
var a=b;

//這時,會釋放掉“hello world”,釋放內存以便再引用

垃圾回收的方法:標記清楚、計數引用。

標記清除

  js中最常用的垃圾收集方式是標記清楚。當變量進入環境(例如,在函數中聲明一個變量)時,就將這個變量標記為“進入環境”。從邏輯上講,永遠不能釋放進入環境的變量所占用的內存,因為只要執行流進入相應的環境,就可能會用到他們。而當變量離開環境時,則將其標記為“離開環境”。

   可以使用任何方式來標記變量。比如,可以通過翻轉某個特殊的位來記錄一個變量何時進入環境,或者使用一個“進入環境的”變量列表及一個“離開環境的”變量列表來跟蹤哪個變量發生變化。

  垃圾收集器在運行的時候會給存儲在內存中的所有變量都加上標記(當然,可以使用任何標記方式)。然后,它會去掉環境中的變量以及被環境中的變量引用的變量標記。而在此之后再被加上標記的變量將被視為准備刪除的變量,原因是環境中的變量已經無法訪問到這些變量了。最后,垃圾收集器完成內存除工作,銷毀那些帶標記的值並回收他們所占用的內存空間。

 

引用計數(不常見)

    引用計數的含義是跟蹤記錄每個值被引用的次數。當聲明了一個變量並將一個引用類型值賦給該變量時,則這個值的引用次數就是1。如果同一個值又被賦給另一個變量,則該值的引用次數加1.相反,如果包含對這個值引用的變量又取的了另一個值,則這個值的引用次數減1.當這個值的引用次數變成0時,則說明沒有辦法再訪問這個值了,因而就可以將其占用的內存空間收回來。這樣,當垃圾收集器下次再運行時,它就會釋放那些引用次數為零的值所占用的內存。

用引用計數法會存在內存泄露,下面來看原因:

function problem() {
var objA = new Object();
var objB = new Object();
objA.someOtherObject = objB;
objB.anotherObject = objA;
}

 

     

在這個例子里面,objA和objB通過各自的屬性相互引用,這樣的話,兩個對象的引用次數都為2,在采用引用計數的策略中,由於函數執行之后,這兩個對象都離開了作用域,函數執行完成之后,這兩個對象都離開了作用域,因此這種相互引用不是個問題。但在采用引用技數策略的實現中,當函數執行完畢后,objectA和objectB還將繼續存在,因為他們的引用次數永遠不會時0.加入這個函數被多次調用,就會導致大量內存得不到回收。為此,Netscape在Navigator4.0中放棄了引用計數方式,轉而采用標記清除來實現其垃圾收集機制。引用計數還會導致其他的麻煩。

特別是在DOM對象中,也容易存在這種問題:

var element=document.getElementById(’‘);
var myObj=new Object();
myObj.element=element;
element.someObject=myObj;

 

這樣就不會有垃圾回收的過程。即使將DOM從頁面中移除,它也永遠不會被回收。,為了避免發生這樣的問題,最好在他們不適用的時候手工斷開原生js對象和dom元素之間的連接。

myobject.element = null;

element.someObject = null;

將變量設置為null意味着切斷變量與它此前引用的值之間的連接。當垃圾收集器下次運行時,就會刪除這些值並回收他們占用的內存。

 

性能問題:

   觸發垃圾收集的變量分配、字面量和(或)數組元素的臨界值被調整為動態修正。如果垃圾收集例程回收的內存分配量低於15%,則變量、字面量和(或)數組元素的臨界值就會加倍。如果例程回收了85%的內存分配量,則將各種臨界值重置回默認值。 


免責聲明!

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



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