最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解JavaScript的垃圾回收機制

 更新時間:2021年11月17日 10:50:50   作者:1900''''s 88 keys  
這篇文章主要為大家介紹了JavaScript的垃圾回收機制,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

為什么需要垃圾回收(GC)

  • 程序和人一樣,生活時間長了會產(chǎn)生垃圾,程序在運行過程中也會產(chǎn)生垃圾,垃圾積攢過多后,會導致程序運行速度變慢。
  • 在JavaScript中的字符串、對象、數(shù)組等數(shù)據(jù)的內(nèi)存是不固定的,只有真正使用的時候才會動態(tài)分配內(nèi)存。
  • 這些數(shù)據(jù)所占的內(nèi)存在不使用時,需要進行釋放,以便再次使用,否者在可用內(nèi)存耗盡造成程序崩潰。

什么是垃圾回收

垃圾回收機制也稱Garbage Collection簡稱GC。在JavaScript中擁有自動的垃圾回收機制,通過一些回收算法,找出不再使用引用的變量或?qū)傩?,由JS引擎按照固定時間間隔周期性的釋放其所占的內(nèi)存空間。在C/C++中需要程序員手動完成垃圾回收。

垃圾產(chǎn)生

當一個對象沒有任何的變量或?qū)傩詫λM行引用,此時我們將永遠無法操作該對象,這種對象就是一個垃圾,這種對象過多會占用大量的內(nèi)存空間,導致程序變慢。

例如:

在這里插入圖片描述

這里我先聲明了一個Person變量,它引用了對象{name: "江流",age: 20},接著我又將這個Person變量指向了另一個對象{name: "心猿", age: 5000},那么之前被引用的對象,現(xiàn)在就成了無用對象,也永遠無法使用操作該對象,這種對象就是一個垃圾。

這種垃圾對象過多,就會占用大量空間,如果一直不釋放就會影響系統(tǒng)性能,重則導致程序崩潰,所以就需要垃圾回收釋放這部分內(nèi)存。

這個過程我們不需要也不能進行垃圾回收的操作。

我們只需要的是將不再使用的對象設置為null即可。

垃圾回收策略

JavaScript 中主要的內(nèi)存管理概念是可達性。大概意思是以某種方式可以訪問到或者可以使用的值,它們就是需要保存在內(nèi)存中,無法訪問,也無法使用的值,則需要被垃圾回收機制回收。

垃圾回收過程是不實時進行的,因為JavaScript是一門單線程的語言,每次執(zhí)行垃圾回收,會使程序應用邏輯暫停,執(zhí)行完垃圾后回收在執(zhí)行應用邏輯,這種行為稱為全停頓,所以一般垃圾回收會在cpu閑時進行。

如何通過某種方式找到所謂的垃圾,是垃圾回收的重點,所以下面常見的算法策略,不過這里只說前兩種:

  1. 引用計數(shù)算法
  2. 標記清除算法
  3. 標記整理
  4. 分代回收

引用計數(shù)標記

策略思想:

  • 跟蹤記錄每個變量值被使用的次數(shù)
  • 當聲明一個變量并且將一個引用類型數(shù)據(jù)賦值給這個變量的時候,這個引用類型數(shù)據(jù)的引用次數(shù)就標記為 1
  • 如果當這個引用類型數(shù)據(jù)又賦值給另一個變量,那么引用次數(shù)就+1
  • 如果變量被其他的值覆蓋,則引用次數(shù)-1
  • 當這個引用類型數(shù)據(jù)的引用次數(shù)變?yōu)?的時候,這個變量就沒有被使用了,也無法訪問,垃圾回收器就會在執(zhí)行時,銷毀引用次數(shù)為0的引用類型數(shù)據(jù),回收其所占用的內(nèi)存空間。

例如:

	let a = {
	    name: "江流",
	    age: 20
		};    	//此時該對象的引用計數(shù)標記為1(a 引用)
	let b = a;	//此時對象的引用計數(shù)標記為2(a、b 引用)
	a = null;	//此時對象的引用計數(shù)標記為1((b 引用))
	b = null;	//此時對象的引用計數(shù)標記為0(無變量引用)
	... 		//等待GC 回收此對象

但是這種方式有個很嚴重的問題 – 循環(huán)引用

循環(huán)引用引發(fā)的問題

在一個函數(shù)中,對象A的屬性指向?qū)ο驜,對象B的屬性指向?qū)ο驛,這個函數(shù)在執(zhí)行完,對象A和B的計數(shù)器也不會為0,影響了正常的GC。

例如下面的例子:

function test()
{
    let A = new Object();
    let B = new Object();
    A.pointer= B;
    B.pointer = A;
}
test();

當對象A和對象B的屬性相互引用這,按照引用計數(shù)策略,他們的引用計數(shù)都是為2,但是在test()執(zhí)行完成后,在函數(shù)執(zhí)行完,函數(shù)作用域中的數(shù)據(jù)對象A和對象B都應該被GC銷毀掉。

如果執(zhí)行多次,將會造成嚴重的內(nèi)存泄漏。

解決方法

在函數(shù)結(jié)束時,將其指向null

//切斷引用關系
A = null;
B = null;

引用計數(shù)算法的優(yōu)缺點

優(yōu)點:

  • 引用計數(shù)為零時,發(fā)現(xiàn)垃圾立即回收
  • 最大限度減少程序暫停

缺點:

  • 無法回收循環(huán)引用的對象
  • 空間開銷比較大

標記清除算法

核心思想

分標記和清除兩個階段完成。

大概過程:

  • 垃圾收集器在運行時會給內(nèi)存中所有的變量都加上一個標記,假設內(nèi)存中所有的對象全部是垃圾,全部標記為0
  • 然后從各個根對象開始遍歷,把不是垃圾的節(jié)點改成1
  • 清理所有標記為0的垃圾,銷毀并回收它們所占用的內(nèi)存空間
  • 最后把所有內(nèi)存中對象標記修改為0,等待下一輪的垃圾回收

在這里插入圖片描述

標記清除算法優(yōu)缺點

優(yōu)點:

  • 實現(xiàn)簡單,標記情況無非是打與不打的兩種情況,通過二進制(0和1)就可以為其標記。
  • 能夠回收循環(huán)引用的對象
  • 是v8引擎使用最多的算法。

缺點:

在清除垃圾之后,剩余對象的內(nèi)存位置是不變的,就會導致空閑內(nèi)存空間不連續(xù)。這樣就出現(xiàn)了內(nèi)存碎片,并且由于剩余空間不是整塊,就需要內(nèi)存分配的問題。

標記整理算法

標記整理(Mark-Compact)算法,就是可以有效的解決,它是在標記結(jié)束后標記整理算法會將不需要清理的對象向內(nèi)存一端移動,最后清理邊界的內(nèi)存。

在這里插入圖片描述

V8引擎的垃圾回收

  • V8引擎的垃圾回收采用標記清除法與分代回收法
  • 分為新生代和老生代

針對不同對象采用不同算法:

(1)新生代:對象的存活時間較短。新生對象或只經(jīng)過一次垃圾回收的對象。

(2)老生代:對象存活時間較長。經(jīng)歷過一次或多次垃圾回收的對象。

回收新生代對象

回收新生代對象主要采用復制算法(Scavenge 算法)加標記整理算法。而Scavenge 算法的具體實現(xiàn),主要采用了Cheney算法。

對象晉升機制

一輪GC還存活的新生代需要晉升。

回收老生代對象

回收老生代對象主要采用標記清除、標記整理、增量標記算法,主要使用標記清除算法,只有在內(nèi)存分配不足時,采用標記整理算法。

  • 首先使用標記清除完成垃圾空間的回收;
  • 采用標記整理進行空間優(yōu)化;
  • 采用增量標記進行效率優(yōu)化;

參考文檔:

JS垃圾回收機制

JavaScript GC 垃圾回收機制

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內(nèi)容!

相關文章

最新評論

阳东县| 西华县| 肇东市| 桐城市| 山阳县| 内乡县| 武宣县| 武城县| 碌曲县| 蕉岭县| 和田县| 东宁县| 龙里县| 博客| 汉源县| 平乡县| 马尔康县| 呼图壁县| 慈溪市| 洛南县| 丁青县| 友谊县| 新宁县| 乃东县| 剑阁县| 白玉县| 阿勒泰市| 霍邱县| 林芝县| 黄平县| 东海县| 长武县| 荣昌县| 永德县| 隆安县| 白城市| 广平县| 孟津县| 宜兴市| 宁南县| 石台县|