JavaScript具有強大的垃圾回收功能,執行環境負責管理代碼執行過程中使用的記憶體。其基本原理是:在執行環境中找出那些不再繼續使用的變數,然後釋放其占用的記憶體。垃圾收集器會按照系統編寫號的時間間隔,周期性地執行操作。 局部變數的生命周期 一個函數中局部變數正常生命周期,局部變數只在函數執行的過程中 ...
JavaScript具有強大的垃圾回收功能,執行環境負責管理代碼執行過程中使用的記憶體。其基本原理是:在執行環境中找出那些不再繼續使用的變數,然後釋放其占用的記憶體。垃圾收集器會按照系統編寫號的時間間隔,周期性地執行操作。
局部變數的生命周期
一個函數中局部變數正常生命周期,局部變數只在函數執行的過程中存在,而在執行的過程中,會為,局部變數在棧或者堆記憶體上分配記憶體空間,以便存儲他們的值。然後再函數中使用這些變數,直至函數執行結束。在這個時候,局部變數就沒有存在的必要了,因此可以釋放它們的記憶體供將來變數使用。
function car() {
var wheel = 100;
return console.log(wheel);//100
}
car();
console.log(wheel);//不能夠訪問,輸出錯誤
垃圾收集器想要收集廢掉的變數,可以在其廢掉的變數打上標記,用於收回占用的記憶體,標識廢掉的變數策咯會因實現而不同,在瀏覽器中實現,通常有兩種策咯。
標記清除
這個JavaScript中最常用的垃圾收集方式,每當一個變數進入環境,就將這個變數標記為“進入環境“。從邏輯上講,永遠不能釋放進入環境的變數所占用的記憶體,因為只要執行流進入相應的環境,就會使用到,而當變數離開環境時,則標記為”離開環境“。
引用計數
引用計數一般的原理是:聲明一個變數,則該值的引用次數加1,如果同一個值又被賦給另一個變數,則該值的引用次數加1,相反,如果包含對這個值引用的變數又取得了另外一個值,那麼這個值引用次數減1,當這個值的引用次數變成0時,則說明沒有辦法再訪問這個值了,因而就可以將其占用的記憶體空間收回來。
問題:迴圈引用
迴圈引用指的是,A對象中包含一個指向B對象的指針,而對象B中也包含一個指向對象A的引用。
function problem() {
var objectA = new Object();
var objectB = new Object();
objectA.prototype1 = objectB;
objectB.prototype2 = objectA;
}
上述代碼中,每當執行完畢後,構造的兩個對象還會繼續存在,因為它們的引用計數策咯實現不會是0。重覆調用會產生大量的記憶體無法收集。
下麵簡單的例子,展示了使用COM對象導致的迴圈引用問題:
var element = document.getElementById("some_element");
var myObject = new Object();
myObject.element = element;
element.someObject = myObject;
這個例子,DOM元素element與一個原生JavaScript對象myObject之間創建了引用。myObject的element屬性指向element對象;而變數element也有一個屬性叫someObject指向myObject,由於存在這個迴圈引用,即使例子中的DOM從頁面中移除,它也永遠不會被回收。
怎麼解決這個問題呢?
在不使用它們的時候手工斷開原生JavaScript對象與DOM之間的連接:
myObject.element = null;
element.someObject = null;
將變數設置null,可以切斷與它之前的連接,在下次運行時就會刪除這些值並回收它們占用的記憶體。
事實上JavaScript是一門具有自動垃圾回收機制的編程語言,我們不必關心記憶體分配問題。
總結:
- 離開作用域的值將被自動標記為可回收,因此將在垃圾收集期間被刪除。
- 標記清除是目前主流的垃圾收集演算法,這種演算法的思想是給當前不使用的值加上標記,然後回收。
- 引用計數,思想是跟蹤記錄所有值被引用的次數。
- 解除變數的引用不僅有助於消除迴圈引用現象,而且對垃圾收集也有好處。
如果有錯誤或者不嚴謹的地方,請務必給予指正,十分感謝。如果您喜歡或者有所啟發,歡迎添加收藏,一起加油學習啊。