JavaScript 垃圾回收

前情提要

面試中老是會遇到 JavaScript 垃圾回收的問題,特地上網查了一下,終於找到一個描述的比較詳細的了, 在這裏與你們 分享一下,本身也作一個備份,以便隨時查看面試

JavaScript 垃圾回收

垃圾回收是一種自動的 內存管理 機制算法

當一個電腦上的動態內存不在須要時,就應該予以釋放,以讓出內存,這種內存資源管理,成爲垃圾回收函數

  • JavaScript 中的內存管理是自動執行的,並且是不可見的。優化

  • 建立基本類型、對象、函數... 全部這些都是須要內存。spa

  • 當再也不須要某樣東西時會發生什麼?JavaScript 引擎是如何發現並清理它?code

可達性

  • JavaScript 中內存管理的主要概念是可達性
  • 「可達性」 值就是那些以某種方式可訪問或可用的值,它們被保存在內存中

可達值

  • 有一組基本的固有可達值,因爲顯而易見的緣由沒法刪除,這些值稱爲根
    • 本地函數的局部變量和參數
    • 當前嵌套調用鏈上的其餘函數的變量和參數
    • 全局變量
    • 還有一些其餘的,內部的
  • 若是引用或引用鏈能夠從根訪問任何其餘值,則認爲該值是可訪問的
    • 若是局部變量中有對象,而且該對象具備引用另外一個對象的屬性,則該對象被視爲可達性,它引用的那些也是能夠訪問的

JavaScript 引擎中有一個後臺進程稱爲垃圾回收器,它監視全部對象,並刪除那些不可訪問的對象

案例

// user 具備對象的引用
let user = {
    name: 'John'
}
// 全局變量「user」引用對象 {name:「John」}
// John 的 「name」 屬性存儲一個基本類型,所以它被繪製在對象中

// user 的值被覆蓋,則引用丟失
user = null
// 如今 John 變成不可達的狀態,沒有辦法訪問它,沒有對它的引用。垃圾回收器將丟棄 John 數據並釋放內存
複製代碼

兩個引用 —— 將引用從 user 複製到 admin

// user 具備對象的引用
let user = {
    name: 'John'
}
let admin = user

user = null
// 該隊愛那個讓然能夠經過 admin 全局訪問變量,因此它在內存中
admin = null
// user 和 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 如今是不可訪問的,並將從內存中刪除全部不可訪問的數據
複製代碼

沒法訪問的數據塊

有可能整個相互鏈接的對象變得不可訪問並從內存中刪除對象

// 源對象同上
// 而後 =>
family = null
// John 和 Ann 仍然鏈接在一塊兒,都有傳入的引用
// 但 "family" 對象已經從根上斷開了連接,再也不有對它的引用,所以下面的整個塊變得不可到達,並將被刪除
複製代碼

內部算法

基本的垃圾回收算法稱爲 「標記-清除」 ,按期執行如下「垃圾回收」步驟:進程

  • 垃圾回收器獲取根並 「標記" (記住) 他們
  • 而後它訪問並 「標記」 全部來自它們的引用
  • 而後它訪問標記的對象並標記它們的引用。全部被訪問的對象都被記住,以便之後再也不訪問同一個對象兩次
  • 以此類推,直到有未訪問的引用(能夠從根訪問)爲止
  • 除標記的對象外,全部對象都被刪除

垃圾收集的工做原理

  • 第一步標記
  • 而後標記 它們的引用 以及 子孫代的引用
  • 進程中 不能訪問的對象 被認爲是 不可訪問的 ,將被 刪除

JavaScript 引擎應用了許多優化,使其運行得更快,而且不影響執行

優化 =>ip

  • 分代回收內存

    • 對象分爲兩組:「新對象」「舊對象」
    • 許多對象出現,完成它們的工做並迅速結束,它們很快就會被清理乾淨
    • 那些活的足夠久的對象,會變」老「,而且不多接受檢查
  • 增量回收

    • 若是有不少對象,而且咱們試圖一次遍歷並標記整個對象集,那麼可能會花費一些時間,並在執行中會有必定的延遲
    • 所以,引擎試圖將垃圾回收分解爲多個部分
    • 而後,各個部分分別執行
    • 這須要額外的標記來跟蹤變化,這樣有不少微小的延遲,而不是很大的延遲
  • 空閒時間回收

    • 垃圾回收器只在 CPU 空閒時運行,以減小對執行的可能影響

面試

  • 什麼是垃圾?
    • 通常來講沒有被引用的對象就是垃圾,就是要被清除
    • 若是幾個對象引用造成一個環,互相引用,但根訪問不到它們,這幾個對象也是垃圾,也要被清除
  • 如何檢測垃圾?
    • 一種算法是標記 標記-清除 算法
相關文章
相關標籤/搜索