來源於 現代 JavaScript 教程
垃圾回收章節雖然在 JavaScript 中不用本身管理內存,可是瞭解原理能夠在關鍵時候快速搜索到解決辦法,畢竟不少時候遇到問題是連搜索什麼關鍵詞都想不起來呀 😂javascript
在個人博客閱讀:https://ssshooter.com/2019-03...java
JavaScript 內存管理於咱們來講是自動的、不可見的。咱們建立的原始類型、對象、函數等等,都會佔用內存。git
當這些數據不被須要後會發生什麼?JavaScript 引擎如何發現並清除他們?github
JavaScript 內存管理的關鍵概念是可觸及(Reachability)。算法
簡單來講,「可觸及」的值就是可訪問的,可用的,他們被安全儲存在內存。編程
如下是一些一定「可觸及」的值,無論出於任何緣由,都不能刪除:安全
這些值都稱爲 root。ssh
假設有一個對象存在於局部變量,它的值引用了另外一個對象,若是這個對象是可觸及的,則它引用的對象也是可觸及的,後面會有詳細例子。函數
JavaScript 引擎有一個垃圾回收後臺進程,監控着全部對象,當對象不可觸及時會將其刪除。post
// user 引用了一個對象 let user = { name: 'John', }
箭頭表明的是對象引用。全局變量 "user"
引用了對象 {name: "John"}
(簡稱此對象爲 John)。John 的 "name"
屬性儲存的是一個原始值,因此無其餘引用。
若是覆蓋 user
,對 John 的引用就丟失了:
user = null
如今 John 變得不可觸及,垃圾回收機制會將其刪除並釋放內存。
若是咱們從 user
複製引用到 admin
:
// user 引用了一個對象 let user = { name: 'John', } let admin = user
若是重複一次這個操做:
user = null
……這個對象是依然能夠經過 admin
訪問,因此它依然存在於內存。若是咱們把 admin
也覆蓋爲 null
,那它就會被刪除了。
這個例子比較複雜:
function marry(man, woman) { woman.husband = man man.wife = woman return { father: man, mother: woman, } } let family = marry( { name: 'John', }, { name: 'Ann', } )
marry
函數讓兩個參數對象互相引用,返回一個包含二者的新對象,結構以下:
暫時全部對象都是可觸及的,但咱們如今決定移除兩個引用:
delete family.father delete family.mother.husband
只刪除一個引用不會有什麼影響,可是兩個引用同時刪除,咱們能夠看到 John 已經不被任何對象引用了:
即便 John 還在引用別人,可是他不被別人引用,因此 John 如今已經不可觸及,將會被移除。
垃圾回收後:
也可能有一大堆互相引用的對象整塊(像個孤島)都不可觸及了。
對上面的對象進行操做:
family = null
內存中的狀況以下:
這個例子展現了「可觸及」這個概念的重要性。
儘管 John 和 Ann 互相依賴,但這仍不足夠。
"family"
對象整個已經切斷了與 root 的鏈接,沒有任何東西引用到這裏,因此這個孤島高不可攀,只能等待被清除。
基礎的垃圾回收算法被稱爲「標記-清除算法」("mark-and-sweep"):
舉個例子,假設對象結構以下:
很明顯右側有一個「孤島」,如今使用「標記-清除」的方法處理它。
首先,標記 root:
而後標記他們的引用:
……標記他們引用的引用:
如今沒有被訪問過的對象會被認爲是不可觸及,他們將會被刪除:
這就是垃圾回收的工做原理。
JavaScript 引擎在不影響執行的狀況下作了不少優化,使這個過程的垃圾回收效率更高:
除此之外還有不少對垃圾回收的優化,在此就不詳細說了,各個引擎有本身的調整和技術,並且這個東西一直隨着引擎的更新換代在改變,若是不是有實在的需求,不值得挖太深。不過若是你真的對此有濃厚的興趣,下面會爲你提供一些拓展連接。
重點:
《The Garbage Collection Handbook: The Art of Automatic Memory Management》(R. Jones 等)一書中說起了現代引擎實現的增強版垃圾回收算法。
若是你熟悉底層編程,能夠閱讀 A tour of V8: Garbage Collection 瞭解更多關於 V8 垃圾回收的細節。
V8 blog 也會常常發佈一些關於內存管理的文章。學習垃圾回收算法最好仍是先學習 V8 的實現,閱讀 Vyacheslav Egorov(V8 工程師之一)的博客。這裏說起 V8 是由於在互聯網上關於 V8 的文章比較多。對於其餘引擎,不少實現都是類似的,可是垃圾回收算法上區別不小。
對引擎的深刻理解在作底層優化的時候頗有幫助。在你熟悉一門語言以後,這是一個明智的研究方向。