溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

JavaScript中的垃圾回收機(jī)制是什么

發(fā)布時(shí)間:2020-11-09 10:24:48 來源:億速云 閱讀:331 作者:小新 欄目:web開發(fā)

這篇文章主要介紹了JavaScript中的垃圾回收機(jī)制是什么,具有一定借鑒價(jià)值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

最近看到一些面試的回顧,不少有被面試官問到談?wù)凧S 垃圾回收機(jī)制,說實(shí)話,面試官會(huì)問這個(gè)問題,說明他最近看到一些關(guān)于 JS 垃圾回收機(jī)制的相關(guān)的文章,為了 B 格,就會(huì)順帶的問問。

最近看到一篇講 JS 垃圾回收的國外文章,覺得講得明白,所以就翻譯過來了,希望對(duì)你們有所幫助。

垃圾回收

JavaScript 中的內(nèi)存管理是自動(dòng)執(zhí)行的,而且是不可見的。我們創(chuàng)建基本類型、對(duì)象、函數(shù)……所有這些都需要內(nèi)存。

當(dāng)不再需要某樣?xùn)|西時(shí)會(huì)發(fā)生什么? JavaScript 引擎是如何發(fā)現(xiàn)并清理它?

可達(dá)性

JavaScript 中內(nèi)存管理的主要概念是可達(dá)性。

簡(jiǎn)單地說,“可達(dá)性” 值就是那些以某種方式可訪問或可用的值,它們被保證存儲(chǔ)在內(nèi)存中。

1. 有一組基本的固有可達(dá)值,由于顯而易見的原因無法刪除。例如:

  • 本地函數(shù)的局部變量和參數(shù)

  • 當(dāng)前嵌套調(diào)用鏈上的其他函數(shù)的變量和參數(shù)

  • 全局變量

  • 還有一些其他的,內(nèi)部的

這些值稱為根。

2. 如果引用或引用鏈可以從根訪問任何其他值,則認(rèn)為該值是可訪問的。

例如,如果局部變量中有對(duì)象,并且該對(duì)象具有引用另一個(gè)對(duì)象的屬性,則該對(duì)象被視為可達(dá)性, 它引用的那些也是可以訪問的,詳細(xì)的例子如下。

JavaScript 引擎中有一個(gè)后臺(tái)進(jìn)程稱為垃圾回收器,它監(jiān)視所有對(duì)象,并刪除那些不可訪問的對(duì)象。

一個(gè)簡(jiǎn)單的例子

下面是最簡(jiǎn)單的例子:

// user 具有對(duì)象的引用
let user = {
  name: "John"
};

JavaScript中的垃圾回收機(jī)制是什么

這里箭頭表示一個(gè)對(duì)象引用。全局變量“user”引用對(duì)象 {name:“John”} (為了簡(jiǎn)潔起見,我們將其命名為John)。John 的 “name” 屬性存儲(chǔ)一個(gè)基本類型,因此它被繪制在對(duì)象中。

如果 user 的值被覆蓋,則引用丟失:

user = null;

JavaScript中的垃圾回收機(jī)制是什么

現(xiàn)在 John 變成不可達(dá)的狀態(tài),沒有辦法訪問它,沒有對(duì)它的引用。垃圾回收器將丟棄 John 數(shù)據(jù)并釋放內(nèi)存。

兩個(gè)引用

現(xiàn)在讓我們假設(shè)我們將引用從 user 復(fù)制到 admin:

// user具有對(duì)象的引用
let user = {
  name: "John"
};
let admin = user;

JavaScript中的垃圾回收機(jī)制是什么

現(xiàn)在如果我們做同樣的事情:

user = null;

該對(duì)象仍然可以通過 admin 全局變量訪問,所以它在內(nèi)存中。如果我們也覆蓋admin,那么它可以被釋放。

相互關(guān)聯(lián)的對(duì)象

現(xiàn)在來看一個(gè)更復(fù)雜的例子, family 對(duì)象:

function marry (man, woman) {
  woman.husban = man;
  man.wife = woman;
  return {
    father: man,
    mother: woman
  }
}
let family = marry({
  name: "John"
}, {
  name: "Ann"
})

函數(shù) marry 通過給兩個(gè)對(duì)象彼此提供引用來“聯(lián)姻”它們,并返回一個(gè)包含兩個(gè)對(duì)象的新對(duì)象。

產(chǎn)生的內(nèi)存結(jié)構(gòu):

JavaScript中的垃圾回收機(jī)制是什么

到目前為止,所有對(duì)象都是可訪問的。

現(xiàn)在讓我們刪除兩個(gè)引用:

delete family.father;
delete family.mother.husband;

JavaScript中的垃圾回收機(jī)制是什么

僅僅刪除這兩個(gè)引用中的一個(gè)是不夠的,因?yàn)樗袑?duì)象仍然是可訪問的。

但是如果我們把這兩個(gè)都刪除,那么我們可以看到 John 不再有傳入的引用:

JavaScript中的垃圾回收機(jī)制是什么

輸出引用無關(guān)緊要。只有傳入的對(duì)象才能使對(duì)象可訪問,因此,John 現(xiàn)在是不可訪問的,并將從內(nèi)存中刪除所有不可訪問的數(shù)據(jù)。

垃圾回收之后:

JavaScript中的垃圾回收機(jī)制是什么

無法訪問的數(shù)據(jù)塊

有可能整個(gè)相互連接的對(duì)象變得不可訪問并從內(nèi)存中刪除。

源對(duì)象與上面的相同。然后:

family = null;

內(nèi)存中的圖片變成:

JavaScript中的垃圾回收機(jī)制是什么

這個(gè)例子說明了可達(dá)性的概念是多么重要。

很明顯,John和Ann仍然鏈接在一起,都有傳入的引用。但這還不夠。

“family”對(duì)象已經(jīng)從根上斷開了鏈接,不再有對(duì)它的引用,因此下面的整個(gè)塊變得不可到達(dá),并將被刪除。

內(nèi)部算法

基本的垃圾回收算法稱為“標(biāo)記-清除”,定期執(zhí)行以下“垃圾回收”步驟:

  • 垃圾回收器獲取根并“標(biāo)記”(記住)它們。

  • 然后它訪問并“標(biāo)記”所有來自它們的引用。

  • 然后它訪問標(biāo)記的對(duì)象并標(biāo)記它們的引用。所有被訪問的對(duì)象都被記住,以便以后不再訪問同一個(gè)對(duì)象兩次。

  • 以此類推,直到有未訪問的引用(可以從根訪問)為止。

  • 除標(biāo)記的對(duì)象外,所有對(duì)象都被刪除。

例如,對(duì)象結(jié)構(gòu)如下:

JavaScript中的垃圾回收機(jī)制是什么

我們可以清楚地看到右邊有一個(gè)“不可到達(dá)的塊”?,F(xiàn)在讓我們看看“標(biāo)記并清除”垃圾回收器如何處理它。

第一步標(biāo)記根

JavaScript中的垃圾回收機(jī)制是什么

然后標(biāo)記他們的引用

JavaScript中的垃圾回收機(jī)制是什么

以及子孫代的引用:

JavaScript中的垃圾回收機(jī)制是什么

現(xiàn)在進(jìn)程中不能訪問的對(duì)象被認(rèn)為是不可訪問的,將被刪除:

JavaScript中的垃圾回收機(jī)制是什么

這就是垃圾收集的工作原理。JavaScript引擎應(yīng)用了許多優(yōu)化,使其運(yùn)行得更快,并且不影響執(zhí)行。

一些優(yōu)化:

  • 分代回收——對(duì)象分為兩組:“新對(duì)象”和“舊對(duì)象”。許多對(duì)象出現(xiàn),完成它們的工作并迅速結(jié) ,它們很快就會(huì)被清理干凈。那些活得足夠久的對(duì)象,會(huì)變“老”,并且很少接受檢查。

  • 增量回收——如果有很多對(duì)象,并且我們?cè)噲D一次遍歷并標(biāo)記整個(gè)對(duì)象集,那么可能會(huì)花費(fèi)一些時(shí)間,并在執(zhí)行中會(huì)有一定的延遲。因此,引擎試圖將垃圾回收分解為多個(gè)部分。然后,各個(gè)部分分別執(zhí)行。這需要額外的標(biāo)記來跟蹤變化,這樣有很多微小的延遲,而不是很大的延遲。

  • 空閑時(shí)間收集——垃圾回收器只在 CPU 空閑時(shí)運(yùn)行,以減少對(duì)執(zhí)行的可能影響。

面試怎么回答

1)問什么是垃圾

一般來說沒有被引用的對(duì)象就是垃圾,就是要被清除, 有個(gè)例外如果幾個(gè)對(duì)象引用形成一個(gè)環(huán),互相引用,但根訪問不到它們,這幾個(gè)對(duì)象也是垃圾,也要被清除。

2)如何檢垃圾

一種算法是標(biāo)記 標(biāo)記-清除 算法,還想說出不同的算法可以參考這里。

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享JavaScript中的垃圾回收機(jī)制是什么內(nèi)容對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,遇到問題就找億速云,詳細(xì)的解決方法等著你來學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI