推薦教學:《JavaScript影片教學》
#最近看到一些面試的回顧,不少有被面試官問到談談JS 垃圾回收機制,說實話,面試官會問這個問題,說明他最近看到一些關於JS 垃圾回收機制的相關的文章,為了B 格,就會順帶的問問。
最近看到一篇講 JS 垃圾回收的國外文章,覺得講得明白,所以就翻譯過來了,希望對你們有所幫助。
JavaScript 中的記憶體管理是自動執行的,而且是看不見的。我們創建基本類型、物件、函數……所有這些都需要記憶體。
當不再需要某樣東西時會發生什麼? JavaScript 引擎是如何發現並清理它?
JavaScript 中記憶體管理的主要概念是可達性。
簡單地說,「可達性」 值就是那些以某種方式可存取或可用的值,它們被保證儲存在記憶體中。
1. 有一組基本的固有可達值,由於顯而易見的原因無法刪除。例如:
本地函數的局部變數和參數
#目前巢狀呼叫鏈上的其他函數的變數和參數
全域變數
還有一些其他的,內部的
##這些值稱為根。
2. 如果引用或引用鏈可以從根存取任何其他值,則認為該值是可存取的。
例如,如果局部變數中有對象,並且該對象具有引用另一個對象的屬性,則該對像被視為可達性, 它引用的那些也是可以訪問的,詳細的例子如下。 JavaScript 引擎中有一個後台程序稱為一個簡單的例子下面是最簡單的例子:// user 具有对象的引用 let user = { name: "John" };這裡箭頭表示一個物件參考。全域變數
「user」引用物件
{name:「John」} (為了簡潔起見,我們將其命名為
John#)。 John 的 「name」 屬性儲存一個基本類型,因此它被繪製在物件中。
user 的值被覆寫,則引用遺失:
user = null;現在
John 變成不可達的狀態,沒有辦法訪問它,沒有對它的引用。垃圾回收器將丟棄 John 資料並釋放記憶體。
兩個引用現在讓我們假設我們將引用從user 複製到
admin:
// user具有对象的引用 let user = { name: "John" }; let admin = user;
現在如果我們做同樣的事情:
user = null;該物件仍然可以透過
admin 全域變數訪問,所以它在記憶體中。如果我們也覆蓋
admin,那麼它可以被釋放。
function marry (man, woman) { woman.husban = 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 現在是無法存取的,並將從記憶體中刪除所有無法存取的資料。
垃圾回收之後: 無法存取的資料區塊有可能整個相互連接的物件變得不可存取並從內存中刪除。 來源物件與上面的相同。然後:family = null;記憶體中的圖片變成:
這個例子說明了可達性的概念是多麼重要。
很明顯,John和Ann仍然連結在一起,都有傳入的引用。但這還不夠。
“family”物件已經從根上斷開了鏈接,不再有對它的引用,因此下面的整個區塊變得不可到達,並將被刪除。
基本的垃圾回收演算法稱為“標記-清除”,定期執行以下“垃圾回收”步驟:
#垃圾回收器取得根並「標記」(記住)它們。
然後它訪問並「標記」所有來自它們的參考。
然後它存取標記的物件並標記它們的參考。所有被訪問的對像都被記住,以便以後不再訪問同一個對象兩次。
以此類推,直到有未存取的參考(可以從根存取)為止。
除標記的物件外,所有物件都被刪除。
例如,物件結構如下:
我們可以清楚地看到右邊有一個「不可到達的區塊」。現在讓我們看看“標記並清除”垃圾回收器如何處理它。
第一步標記根
#然後標記他們的引用
以及子孫代的引用:
現在進程中不能存取的物件被認為是不可存取的,將被刪除:
這就是垃圾收集的工作原理。 JavaScript引擎應用了許多優化,使其運行得更快,並且不影響執行。
一些優化:
分代回收——物件分為兩組:「新物件」和「舊物件」。許多物件出現,完成它們的工作並迅速結 ,它們很快就會被清理乾淨。那些活得足夠久的對象,會變“老”,並且很少接受檢查。
增量回收——如果有很多對象,並且我們試圖一次遍歷並標記整個物件集,那麼可能會花費一些時間,並在執行中會有一定的延遲。因此,引擎試圖將垃圾回收分解為多個部分。然後,各個部分分別執行。這需要額外的標記來追蹤變化,這樣有很多微小的延遲,而不是很大的延遲。
空閒時間收集——垃圾回收器只在 CPU 空閒時運行,以減少對執行的可能影響。
1)問什麼是垃圾
一般來說沒有被引用的物件就是垃圾,就是要被清除, 有個例外如果幾個物件引用形成一個環,互相引用,但根訪問不到它們,這幾個物件也是垃圾,也要被清除。
2)如何檢垃圾
一種演算法是標記 標記-清除 演算法,還想說出不同的演算法可以參考這裡。
更深入的講解 V8 之旅: 垃圾回收器
更多程式相關知識,請造訪:程式入門! !
以上是了解JavaScript中的垃圾回收機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!