javascript垃圾回收機制
javascript是一門具有自動垃圾收集機制的程式語言,開發人員不必關心記憶體分配和回收問題。這種垃圾收集機制的原理就是:找出那些不再繼續使用的變數,然後釋放其佔用的記憶體。在javascript中垃圾回收機制有兩種,標記清除和引用計數,和java類似。
垃圾收集機制的原理:
垃圾收集器會按照固定的時間間隔,週期性的找出不再繼續使用的變數,然後釋放其佔用的記憶體。
什麼叫不再繼續使用的變數?
不再使用的變數也就是生命週期結束的變數,是區域性變數,區域性變數只在函式的執行過程中存在,當函式執行結束,沒有其他引用(閉包),那麼該變數會被標記回收。
全域性變數的生命週期直至瀏覽器解除安裝頁面才會結束,也就是說全域性變數不會被當成垃圾回收。
標記清除:當前採用的垃圾收集策略
工作原理:
當變數進入環境時(例如在函式中宣告一個變數),將這個變數標記為“進入環境”,當變數離開環境時,則將其標記為“離開環境”。標記“離開環境”的就回收記憶體。
工作流程:
垃圾收集器會在執行的時候會給儲存在記憶體中的所有變數都加上標記。去掉環境中的變數以及被環境中的變數引用的變數的標記。那些還存在標記的變數被視為準備刪除的變數。最後垃圾收集器會執行最後一步記憶體清除的工作,銷燬那些帶標記的值並回收它們所佔用的記憶體空間。
到2008年為止,IE、Chorme、Fireofx、Safari、Opera 都使用標記清除式的垃圾收集策略,只不過垃圾收集的時間間隔互有不同。
引用計數:被廢棄的垃圾收集策略
引用計數的含義是跟蹤每個值被引用的次數。當聲明瞭一個變數並將一個引用型別賦值給該變數時,則這個值的引用次數為1.如果同一個只又被賦給另一個變數,則該值的引用次數加1。當這個值的引用次數為0時,則說明沒有辦法再訪問這個值了,就可以將空間回收。但這種方式有一個很大的問題,當兩個物件相互引用時就出現了迴圈引用的問題,這兩個物件永遠不能被回收。所以這種垃圾收集策略不常見,因為目前javascript引擎不能再使用這種演算法。
解除變數的引用不僅有助於消除迴圈引用現象,而且對垃圾收集也有好處。為了確保有效的回收記憶體,應及時解除不再使用的全域性物件、全集物件屬性以及迴圈引用變數的引用。
在IE9以下BOM和DOM物件就是使用C++以COM物件的形式實現的。
COM的垃圾收集機制採用的就是引用計數策略,這種機制在出現迴圈引用的時候永遠都釋放不掉記憶體。
var element = document.getElementById('something');
var myObject = new Object();
myObject.element = element; // element屬性指向dom
element.someThing = myObject; // someThing回指myObject 出現迴圈引用(兩個物件一直互相包含 一直存在計數)。
解決方式是,當我們不使用它們的時候,手動切斷連結:
myObject.element = null;
element.someThing = null;
IE9把BOM和DOM物件轉為了真正的js物件,避免了使用這種垃圾收集策略,消除了IE9以下常見的記憶體洩漏的主要原因。