1. 程式人生 > >JavaScript中的垃圾收集機制(標記清除和引用計數)

JavaScript中的垃圾收集機制(標記清除和引用計數)

垃圾收集機制

JavaScript 具有自動垃圾收集機制,也就是說,執行環境會負責管理程式碼執行過程中使用的記憶體。這樣我們在編寫 JavaScript 程式碼時就不需在關心記憶體使用問題了,所需記憶體分配和已用記憶體的回收完全實現了自動管理。

這種垃圾收集機制的原理其實非常簡單:
找出那些不再使用的變數,然後釋放其佔用的記憶體。為此,垃圾收集器會按照固定的時間間隔(或程式碼執行中預定的收集時間),週期性的執行這一操作。


區域性變數的生命週期:

區域性變數只在函式的執行過程中存在。
在這個過程中,首先會為區域性變數在棧(或堆)記憶體上分配相應空間,以便儲存他們的值。然後在函式中使用這些變數,直到函式執行結束

。此時,區域性變數就沒有存在的必要了,因此可以釋放它們的記憶體以供將來使用


在垃圾自動收集機制中,最關鍵的在於如何判斷這個變數是否還有存在的必要。也就是判斷是否該釋放這個變數的記憶體。因此,垃圾收集器必須跟蹤哪個變數有用哪個變數沒用,對於不再有用的變數打上標記,以備將來回收記憶體
實現這個功能通常有兩個策略:標記清除引用計數

1. 標記清除

標記清除是 JavaScript 中最常用的垃圾收集方式。

當變數進入環境(例如,在函式中宣告一個變數)時,將這個變數標記為 “進入環境” 。從邏輯上講,永遠不能釋放進入環境的變數所佔用的記憶體,因為我們在這個環境中可能隨時會用到它們。當變數離開環境時,則將其標記為 “離開環境”。

2. 引用計數

另一種不太常見的垃圾收集策略就是引用計數。

引用計數的含義就是跟蹤記錄每個值被引用的次數。當聲明瞭一個變數並將一個引用型別值賦給該變數時,這個值的引用次數就是 1。如果同一個值又被賦值給另一個變數,則引用次數加 1。相反,如果包含對這個值的引用的變數有取了另一個值,則引用次數減 1。當這個值的引用次數變為 0 時,說明已經沒法再訪問這個值了,因此可以將其佔用的記憶體回收了。

引用計數策略有一個很嚴重的問題:迴圈引用。
如果物件 A 中包含一個指標指向物件 B,而物件 B 中也包含一個指標指向物件 A。那麼這兩個物件引用次數都是 2,但實際上已經可以回收了。若這種函式被反覆多次呼叫,會導致大量記憶體得不到回收。