淺談 JavaScript 內(nèi)存管理與垃圾回收

寫過(guò)C語(yǔ)言的都清楚,我們需要時(shí)時(shí)刻刻關(guān)心處理程序的內(nèi)存使用情況恢总,這無(wú)形的給程序員增添了很多負(fù)擔(dān)迎罗,但是在后期出現(xiàn)的一些語(yǔ)言中漸漸的都加入了內(nèi)存自動(dòng)管理和垃圾回收機(jī)制,這樣一來(lái)我們就不必再關(guān)心程序運(yùn)行的內(nèi)存使用情況片仿,同樣的在JavaScript中也有內(nèi)存管理和垃圾回收纹安。但是這樣漸漸的內(nèi)存中的東西就離我們?cè)絹?lái)越遠(yuǎn),直至現(xiàn)在很多入門前端的對(duì)內(nèi)存的情況一概不知砂豌,我也是厢岂,當(dāng)然這是錯(cuò)誤的。

內(nèi)存分配

內(nèi)存分配的最終目的就是為了配合垃圾回收機(jī)制阳距,使得程序運(yùn)行時(shí)占用內(nèi)存更少塔粒,從而效率更高。

我們都知道數(shù)據(jù)類型有兩種:基礎(chǔ)類型和引用類型筐摘,不同的類型采用著不同的存儲(chǔ)方式卒茬。

基礎(chǔ)類型與棧內(nèi)存

基礎(chǔ)類型值包括:undefinednull咖熟、boolean圃酵、numberstringsymbol球恤。這些類型的值大多有固定的大小辜昵,JavaScript將它們保存在棧內(nèi)存中直接按值引用荸镊。
棧是一種線性的數(shù)據(jù)結(jié)構(gòu)咽斧,典型特點(diǎn)是先進(jìn)后出, 后進(jìn)先出,當(dāng)JavaScript中一個(gè)方法執(zhí)行的時(shí)候堪置,該方法就建立一個(gè)內(nèi)存棧,然后將方法中定義的變量放入棧中张惹,當(dāng)我們需要的時(shí)候直接按值引用即可舀锨。當(dāng)方法執(zhí)行結(jié)束后就銷毀。

引用類型與堆內(nèi)存

JavaScript的引用類型大多長(zhǎng)度不固定宛逗,比如Array坎匿,它的長(zhǎng)度并不是固定的。他的值保存在堆內(nèi)存的對(duì)象中雷激。然后將它的地址放入棧中替蔬,而且不允許我們直接訪問(wèn)堆內(nèi)存中的位置,所以我們操作的都是對(duì)象的引用屎暇,并不是實(shí)際的對(duì)象承桥。
在程序中創(chuàng)建一個(gè)對(duì)象的成本是比較大的,在創(chuàng)建完成后就會(huì)被保存在堆數(shù)據(jù)區(qū)根悼,并不會(huì)隨著方法的結(jié)束而銷毀凶异。只有當(dāng)這個(gè)對(duì)象沒(méi)有被任何引用變量引用的時(shí)候,垃圾回收的時(shí)候才會(huì)回收掉它挤巡。

垃圾回收

JavaScript具有自動(dòng)垃圾收集機(jī)制剩彬,執(zhí)行環(huán)境會(huì)負(fù)責(zé)找出那些不再繼續(xù)使用的變量然后釋放其占用的內(nèi)存。對(duì)于找出垃圾的方法通常有兩個(gè)策略:

標(biāo)記清除

這是最常用的垃圾收集機(jī)制矿卑。這種算法假定一個(gè)根對(duì)象喉恋,然后遍歷所有從根開(kāi)始引用的對(duì)象,垃圾收集器在運(yùn)行的時(shí)候會(huì)將他們加上標(biāo)記母廷,然后去掉環(huán)境中使用的變量和被他們引用的變量的標(biāo)記瀑晒。之后再被加上標(biāo)記的變量就是要?jiǎng)h除的,垃圾收集器將其釋放完成一次工作徘意。

引用計(jì)數(shù)

這種機(jī)制為每一個(gè)值標(biāo)記被引用的次數(shù)并追蹤苔悦,當(dāng)被其他變量引用的時(shí)候就加一,反之就減一椎咧,當(dāng)引用次數(shù)變成 0 的時(shí)候就是需要回收的了玖详。垃圾收集器下次運(yùn)行的時(shí)候就會(huì)把它釋放掉。但是這樣會(huì)有一個(gè)問(wèn)題勤讽,比如:

let obj1 = new Object();
let obj2 = new Object();

obj1.attr1 = obj2;
obj2.attr2 = obj1;

在這里obj1obj2各自互相引用蟋座,這塊語(yǔ)句執(zhí)行過(guò)后他們的引用次數(shù)永遠(yuǎn)不會(huì)變成 0 ,也就得不到回收脚牍,如果存在大量這種情況的話內(nèi)存就出問(wèn)題了向臀。只要有出現(xiàn)循環(huán)引用的地方,這種機(jī)制就會(huì)出問(wèn)題诸狭。所以它無(wú)法處理循環(huán)引用的問(wèn)題券膀。

V8引擎的垃圾回收

V8 采用一種叫做分代回收的策略君纫。將內(nèi)存分為新生代和老生代,新生代存放存活時(shí)間段的對(duì)象芹彬,老生代則存放存活時(shí)間長(zhǎng)或者常駐內(nèi)存的對(duì)象蓄髓。

  • 大多數(shù)的對(duì)象會(huì)被分配到新生代內(nèi)存中,回收算法將這里的內(nèi)存空間一分為二舒帮,一個(gè)處于使用狀態(tài)一個(gè)處于閑置狀態(tài)会喝。分配對(duì)象的時(shí)候先把它放在使用區(qū)中,開(kāi)始垃圾回收的時(shí)候就檢查使用區(qū)中存活的對(duì)象玩郊,將他們復(fù)制到閑置區(qū)中并適當(dāng)緊縮肢执,最后釋放使用區(qū)上剩下的數(shù)據(jù)。然后閑置區(qū)變成使用區(qū)译红,使用區(qū)變成閑置區(qū)蔚万,循環(huán)往復(fù)。

  • 當(dāng)一個(gè)對(duì)象經(jīng)過(guò)多次清理后依然存在临庇,它就會(huì)被移動(dòng)到老生代反璃,稱為晉升

  • 老生代占用內(nèi)存較多假夺,主要采用標(biāo)記清除標(biāo)記整理兩個(gè)策略淮蜈。在標(biāo)記階段遍歷堆中的所有對(duì)象,標(biāo)注那些活著的對(duì)象已卷,然后在清除階段標(biāo)記清除會(huì)清除掉沒(méi)有被標(biāo)記的對(duì)象梧田。但是這會(huì)產(chǎn)生內(nèi)存碎片。標(biāo)記清理在清理的時(shí)候可以解決碎片問(wèn)題侧蘸,它將活著的對(duì)象向內(nèi)存中的一段移動(dòng)裁眯,然后清理掉邊界外的內(nèi)存。不過(guò)這個(gè)過(guò)程涉及到數(shù)據(jù)移動(dòng)讳癌,所以效率不是很高穿稳。

除此之外 V8 中還使用了增量標(biāo)記,讓垃圾回收與應(yīng)用邏輯交替進(jìn)行晌坤,以減少垃圾回收時(shí)的停頓時(shí)間逢艘;在標(biāo)記完成后還可以惰性清理;以及后期中引入了并行標(biāo)記和并行清理骤菠,通過(guò)并行來(lái)利用多核 CPU 性能它改。這些無(wú)疑讓 V8 成為了最出色的 JavaScript 引擎。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末商乎,一起剝皮案震驚了整個(gè)濱河市央拖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖鲜戒,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件专控,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡袍啡,警方通過(guò)查閱死者的電腦和手機(jī)踩官,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門却桶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)境输,“玉大人,你說(shuō)我怎么就攤上這事颖系⌒崞剩” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵嘁扼,是天一觀的道長(zhǎng)信粮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)趁啸,這世上最難降的妖魔是什么强缘? 我笑而不...
    開(kāi)封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮不傅,結(jié)果婚禮上旅掂,老公的妹妹穿的比我還像新娘。我一直安慰自己访娶,他們只是感情好商虐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著崖疤,像睡著了一般秘车。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上劫哼,一...
    開(kāi)封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天叮趴,我揣著相機(jī)與錄音,去河邊找鬼权烧。 笑死疫向,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的豪嚎。 我是一名探鬼主播搔驼,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼侈询!你這毒婦竟也來(lái)了舌涨?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤扔字,失蹤者是張志新(化名)和其女友劉穎囊嘉,沒(méi)想到半個(gè)月后温技,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扭粱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年舵鳞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片琢蛤。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蜓堕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出博其,到底是詐尸還是另有隱情套才,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布慕淡,位于F島的核電站背伴,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏峰髓。R本人自食惡果不足惜傻寂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望携兵。 院中可真熱鬧疾掰,春花似錦、人聲如沸眉孩。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)浪汪。三九已至巴柿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間死遭,已是汗流浹背广恢。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呀潭,地道東北人钉迷。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像钠署,于是被迫代替她去往敵國(guó)和親糠聪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容