1. 程式人生 > >JavaScript 的記憶體洩露和垃圾回收

JavaScript 的記憶體洩露和垃圾回收

什麼是記憶體洩露 ?

  • 任何程式語言,在執行時都需要使用到記憶體,比如在一個函式中, var arr = [1, 2, 3, 4, 5]; 這麼一個數組,就需要記憶體。

  • 但是,在使用了這些記憶體之後, 如果後面他們不會再被用到,但是還沒有及時釋放,這就叫做記憶體洩露(memory leak)。如果出現了記憶體洩露,那麼有可能使得記憶體越來越大,而導致瀏覽器崩潰。

  • C語言是通過手動分配和釋放記憶體的, 如通過malloc分配,通過free釋放,這種方式是比較麻煩的。而java、c#、js等是為了解放程式設計師的負擔,提出了程式自動釋放記憶體,這種方式就是垃圾回收機制

JavaScript 中的兩種 垃圾回收機制

引用計數

即跟蹤記錄每個值被引用的次數,當聲明瞭一個變數並將一個引用型別賦值給該變數時,則這個值的引用次數就是1; 相反,如果包含對這個值引用的變數又取得了另外一個值,那麼這個值的引用次數就減1;當引用次數變為0的時候,則說明沒有辦法再訪問到這個值了,所以,就可以把其所佔用的記憶體空間給收回來。 這樣,垃圾收集器下次再執行時,他就會釋放哪些引用次數為0的值所佔的記憶體。

DEMO:

function
test(){

 var a = {} ; //a的引用次數為0

 var b = a ; //a的引用次數加1,為1

 var c =a; //a的引用次數再加1,為2

 var b ={}; //a的引用次數減1,為1

}
複製程式碼

標記清除

  這是JavaScript中最常用的垃圾回收機制。當變數進入環境時,就標記這個變數為“進入環境”,邏輯上說,永遠不能釋放進入環境的變數所佔用的記憶體,因為一旦進入環境就有可能隨時用到他們,當變數離開環境的時候,將其標記為“離開環境”。

DEMO:

function
test(){

 var a = 10 ; 
 //被標記 ,進入環境

 var b = 20 ; 
 //被標記 ,進入環境

}

test(); //執行完畢 之後 a、b又被標離開環境,被回收。
複製程式碼

什麼時候觸發 垃圾回收

ie

垃圾回收器週期性執行,如果分配的記憶體非常多,那麼回收工作也會很艱鉅,確定垃圾回收時間間隔就變成了一個值得思考的問題。IE6的垃圾回收是根據記憶體分配量執行的,當環境中存在256個變數、4096個物件、64k的字串任意一種情況的時候就會觸發垃圾回收器工作,看起來很科學,不用按一段時間就呼叫一次,有時候會沒必要,這樣按需呼叫不是很好嗎?但是如果環境中就是有這麼多變數等一直存在,現在指令碼如此複雜,很正常,那麼結果就是垃圾回收器一直在工作,這樣瀏覽器就沒法兒玩兒了。

微軟在IE7中做了調整,觸發條件不再是固定的,而是動態修改的,初始值和IE6相同,如果垃圾回收器回收的記憶體分配量低於程式佔用記憶體的15%,說明大部分記憶體不可被回收,設的垃圾回收觸發條件過於敏感,這時候把臨街條件翻倍,如果回收的記憶體高於85%,說明大部分記憶體早就該清理了,這時候把觸發條件置回。這樣就使垃圾回收工作職能了很多

合理的 GC 方案

1)、Javascript引擎基礎GC方案是(simple GC):mark and sweep(標記清除),即:

(1)遍歷所有可訪問的物件。

(2)回收已不可訪問的物件。


作者:leoeo
連結:https://juejin.im/post/5a77fdf7f265da4e732ea741
來源:掘金
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。