二兜材、垃圾回收原理淺析
現(xiàn)在各大瀏覽器通常用采用的垃圾回收有兩種方法:標(biāo)記清除档押、引用計(jì)數(shù)。
1锅论、標(biāo)記清除
這是javascript中最常用的垃圾回收方式讼溺。當(dāng)變量進(jìn)入執(zhí)行環(huán)境是,就標(biāo)記這個變量為“進(jìn)入環(huán)境”棍厌。從邏輯上講肾胯,永遠(yuǎn)不能釋放進(jìn)入環(huán)境的變量所占用的內(nèi)存竖席,因?yàn)橹灰獔?zhí)行流進(jìn)入相應(yīng)的環(huán)境耘纱,就可能會用到他們。當(dāng)變量離開環(huán)境時毕荐,則將其標(biāo)記為“離開環(huán)境”束析。 垃圾收集器在運(yùn)行的時候會給存儲在內(nèi)存中的所有變量都加上標(biāo)記。然后憎亚,它會去掉環(huán)境中的變量以及被環(huán)境中的變量引用的標(biāo)記员寇。而在此之后再被加上標(biāo)記的變量將被視為準(zhǔn)備刪除的變量,原因是環(huán)境中的變量已經(jīng)無法訪問到這些變量了第美。最后蝶锋。垃圾收集器完成內(nèi)存清除工作,銷毀那些帶標(biāo)記的值什往,并回收他們所占用的內(nèi)存空間扳缕。
關(guān)于這一塊,建議讀讀Tom大叔的幾篇文章别威,關(guān)于作用域鏈的一些知識詳解躯舔,讀完差不多就知道了,哪些變量會被做標(biāo)記省古。
2粥庄、引用計(jì)數(shù)
另一種不太常見的垃圾回收策略是引用計(jì)數(shù)。引用計(jì)數(shù)的含義是跟蹤記錄每個值被引用的次數(shù)豺妓。當(dāng)聲明了一個變量并將一個引用類型賦值給該變量時惜互,則這個值的引用次數(shù)就是1。相反琳拭,如果包含對這個值引用的變量又取得了另外一個值训堆,則這個值的引用次數(shù)就減1。當(dāng)這個引用次數(shù)變成0時臀栈,則說明沒有辦法再訪問這個值了蔫慧,因而就可以將其所占的內(nèi)存空間給收回來。這樣权薯,垃圾收集器下次再運(yùn)行時姑躲,它就會釋放那些引用次數(shù)為0的值所占的內(nèi)存睡扬。 但是用這種方法存在著一個問題,下面來看看代碼:
[](javascript:void(0);)
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n10" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">function problem() {
var objA = new Object();
var objB = new Object();
?
objA.someOtherObject = objB;
objB.anotherObject = objA;
}</pre>
](javascript:void(0);)
在這個例子中黍析,objA
和objB
通過各自的屬性相互引用卖怜;也就是說這兩個對象的引用次數(shù)都是2。在采用引用計(jì)數(shù)的策略中阐枣,由于函數(shù)執(zhí)行之后马靠,這兩個對象都離開了作用域,函數(shù)執(zhí)行完成之后蔼两,objA
和objB
還將會繼續(xù)存在甩鳄,因?yàn)樗麄兊囊么螖?shù)永遠(yuǎn)不會是0。這樣的相互引用如果說很大量的存在就會導(dǎo)致大量的內(nèi)存泄露额划。
優(yōu)化的方式
盡量少用new
的方式 因?yàn)樗鼤男麻_辟一個地址空間來占用內(nèi)存
少定義全局的變量(全局的變量不會被垃圾回收)
想要把數(shù)組清空有兩種方式 一種是直接從新賦值一個空的數(shù)組 這種會占用一點(diǎn)內(nèi)存 盡量使用
arr.lenght = 0
的方式去清空數(shù)組