垃圾回收是編程語言必不可少的環節,當一個變數被定義時,會在系統中分配一個記憶體來儲存變數的值,而當這個變數不在使用的時候就需要對變數進行回收,釋放記憶體。 如果垃圾不進行回收就會照成記憶體泄露的情況,記憶體泄露可能會導致卡頓或者崩潰。 在編程語言中,c 語言需要手動對垃圾進行回收,而java 和 javas ...
垃圾回收是編程語言必不可少的環節,當一個變數被定義時,會在系統中分配一個記憶體來儲存變數的值,而當這個變數不在使用的時候就需要對變數進行回收,釋放記憶體。
如果垃圾不進行回收就會照成記憶體泄露的情況,記憶體泄露可能會導致卡頓或者崩潰。
在編程語言中,c 語言需要手動對垃圾進行回收,而java 和 javascript 系統會自動進行垃圾回收。
javascript 中的垃圾回收機制有兩種:
一、引用計數
引用計數回收機制是通過對一個值的引用次數進行統計,當這個值被付給一個變數時會給這個值標記為引用一次,如果這個值在被付給另外一個變數,則會給這個變數標記為引用兩次。當這個值的引用次數為0時,下次垃圾回收時會把這個值進行回收。
但是引用計數垃圾回收機制有個問題,就是迴圈引用,導致垃圾不能被回收。
1 function problem () { 2 var objectA = new Object(); 3 var objectB = new Object(); 4 5 objectA.someOtherObject = objectB; 6 objectB.anotherObject = objectA; 7 } 8 9 problem();
上面為《JavaScript 高級程式設計》中的一個例子。
當執行problem 函數時創建一個objectA 變數指向一個空的Object、創建一個objectB 變數執行一個空的Object。
並將objectB 的引用賦值給objectA的someOtherObject 屬性,將objectA 的引用賦值給objectB的anotherObject 屬性。此時兩個空對象的引用數量都為2(空對象為new Object() 在賦值給objectA 時引用計數加1,在賦值給objectB.anotherObject 時加1,所以此時objectA 所指向的空對象的引用為2,objectB 指向的空對象引用次數同理)。
因此在函數執行結束後objectA 和 objectB 所指向的空對象都不能被回收,如果多次執行problem函數會導致記憶體中有大量的對象無法被清除。
所以此垃圾回收機制被瀏覽器淘汰,各瀏覽器選擇了使用另外一個垃圾回收機制進行垃圾回收--標記清除
二、標記清除
標記清除是通過變數進入環境(即在執行預編譯的時候將變數放入到作用域中)時對變數進行標記(標記為進入進入),當變數離開環境時又會被標記為離開環境。當垃圾回收時會將記憶體中的所有變數標記為可回收,然後再將環境中的變數和被環境中變數引用的變數的標記清除,然後對被標記的變數進行銷毀和回收。