一、垃圾回收機制的必要性 由於字元串、對象和數組沒有固定大小,所以當它們的大小已知時,才能對它們進行動態的存儲分配。JavaScript程式每次創建字元串、數組或對象時,解釋器都必須分配記憶體來存儲那個實體。只要像這樣動態地分配了記憶體,最終都要釋放這些記憶體以便它們能夠被再用,否則,JavaScript ...
一、垃圾回收機制的必要性
由於字元串、對象和數組沒有固定大小,所以當它們的大小已知時,才能對它們進行動態的存儲分配。JavaScript程式每次創建字元串、數組或對象時,解釋器都必須分配記憶體來存儲那個實體。只要像這樣動態地分配了記憶體,最終都要釋放這些記憶體以便它們能夠被再用,否則,JavaScript的解釋器將會消耗完系統中所有可用的記憶體,造成系統崩潰。
JavaScript的解釋器可以檢測到何時程式不再使用一個對象了,當它確定了一個對象是無用的時候,它就知道不再需要這個對象,可以把它所占用的記憶體釋放掉了。
二、垃圾回收機制
Js具有自動垃圾回收機制。垃圾收集器會按照固定的時間間隔周期性的執行。
1、標記清除(常用)
當一塊記憶體中的數據能夠被訪問時,垃圾回收器就認為"該數據能夠被獲得"。不能夠被獲得的數據,就會被打上標記,並回收記憶體空間。這種方式叫作標記---清除演算法。
這個演算法會設置一個全局對象,並定期地從全局對象開始查找,垃圾回收器會找到所有可以獲得與不能獲得的數據。
工作流程:
(1)垃圾回收器,在運行的時候會給存儲在記憶體中的所有變數都加上標記。
(2)去掉環境中的變數以及被環境中的變數引用的變數的標記。
(3)再被加上標記的會被視為準備刪除的變數。
(4)垃圾回收器完成記憶體清除工作,銷毀那些帶標記的數據並回收它們所占用的記憶體空間。
註意:在局部作用域中,當函數執行完畢後,局部變數也就沒有存在的必要了,因此垃圾收集器很容易做出判斷並回收。但在全局中,變數什麼時候需要自動釋放記憶體空間則很難判斷,因此我們在開發時,應儘量避免使用全局變數。如果使用了全局變數,則建議不再使用它時,通過釋放變數方式,以確保能夠及時回收記憶體空間。
2、引用計數
跟蹤記錄每個值被引用的次數。例當變數聲明,第一次賦值時記為1,然後當這個變數值改變時,記錄為0,將計數為0的回收。
工作流程:
(1)聲明瞭一個變數並將一個引用類型的值賦值給這個變數,這個引用類型值的引用次數就是1。
(2)同一個值又被賦值給另一個變數,這個引用類型值的引用次數加1.
(3)當包含這個引用類型值的變數又被賦值成另一個值了,那麼這個引用類型值的引用次數減1.
(4)當引用次數變成0時,說明沒辦法訪問這個值了。
(5)當垃圾收集器下一次運行時,它就會釋放引用次數是0的值所占的記憶體。
但是當迴圈引用的時候就會釋放不掉記憶體。
1 function problem() { 2 var objA = new Object(); 3 var objB = new Object(); 4 5 objA.someOtherObject = objB; 6 objB.anotherObject = objA; 7 }
當objA和objB通過各自的屬性相互引用,也就是說這兩個對象的引用次數都是2。在採用引用計數的策略中,由於函數執行之後,這兩個對象都離開了作用域,函數執行完成之後,objA和objB還將會繼續存在,因為他們的引用次數永遠不會是0。這樣的相互引用如果說很大量的存在就會導致大量的記憶體泄露。
因為IE中的BOM、DOM的實現使用了COM,而COM對象使用的垃圾收集機制是引用計數策略。所以會存在迴圈引用的問題。
解決:手工斷開js對象和DOM之間的鏈接,賦值為null。IE9把DOM和BOM轉換成真正的JS對象了,所以避免了這個問題。