隨手記一記之【js 垃圾收集】

JS 具有自動(dòng)垃圾收集機(jī)制,因此開發(fā)人員不用關(guān)心內(nèi)存的使用問(wèn)題。其垃圾收集機(jī)制原理很簡(jiǎn)單:就是找出不需要繼續(xù)使用的變量,然后釋放其占用內(nèi)存。
JS 垃圾收集有兩種方式,標(biāo)記清除和引用計(jì)數(shù)。

標(biāo)記清除

這是 JS 種最常用的垃圾收集方式。

當(dāng)變量進(jìn)入環(huán)境時(shí),就會(huì)給其一個(gè)“進(jìn)入環(huán)境”的標(biāo)記。當(dāng)變量離開環(huán)境時(shí),就給其一個(gè)“離開環(huán)境”的標(biāo)記。用什么方式標(biāo)記不重要,每當(dāng)垃圾收集器運(yùn)行時(shí)則將“離開環(huán)境”標(biāo)記的變量銷毀,釋放其占用內(nèi)存。

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

引用計(jì)數(shù)的方式則是記錄其引用數(shù)。當(dāng)一個(gè)引用類型的值被賦值給一個(gè)新申明變量時(shí),這個(gè)值的引用次數(shù)是1。如果另一個(gè)變量引用了這個(gè)值,那么它的引用次數(shù)加1。反之,當(dāng)引用這個(gè)值的變量引用了其他的值,則這個(gè)值的引用次數(shù)減1。當(dāng)其引用次數(shù)為0時(shí)就意味著不能再獲取這個(gè)值,即可以將它回收。垃圾回收器運(yùn)行時(shí),即可釋放其占用內(nèi)存。

但是引用計(jì)數(shù)方式有一個(gè)很嚴(yán)重的問(wèn)題,那就是循環(huán)引用。例如:

function foo(){
  var objectA = {}
  var objectB = {}
  
  objectA.child = objectB
  objectB.child = objectA
}

此時(shí),objectA 和 objectB 的引用次數(shù)都是2。而且不會(huì)減少到0,那么引用計(jì)數(shù)的垃圾收集方式下objectA、objectB將永遠(yuǎn)不會(huì)被回收。如果是標(biāo)記清除方式,當(dāng)函數(shù) foo 執(zhí)行完畢后,其內(nèi)部變量都離開了作用域,就可以被垃圾收集器釋放。

當(dāng)這個(gè)函數(shù)被大量使用時(shí),就會(huì)導(dǎo)致大量?jī)?nèi)存被占用,并且一直得不到回收。

IE的 BOM 和 DOM

IE 的 BOM 和 DOM 是使用C++以 COM(Component Object Model,組件對(duì)象模型)對(duì)象的形式實(shí)現(xiàn)的,而 COM 對(duì)象的垃圾收集機(jī)制采用的就是引用計(jì)數(shù)方式。所以在 IE 中涉及 COM 對(duì)象,就會(huì)存在循環(huán)引用問(wèn)題。例如

var element = document.getElementById('id')
var someObject = {}

someObject.element = element
element.otherObject = someObject

此時(shí)的 element 永遠(yuǎn)的不會(huì)被回收。那么為了避免這樣的問(wèn)題,只有手動(dòng)的將其引用設(shè)為 null。

someObject.element = null
element.otherObject = null

為了解決這個(gè)問(wèn)題,IE9把 BOM 和 DOM 對(duì)象都轉(zhuǎn)換成了真正的 js 對(duì)象。這樣,就避免了兩種垃圾收集算法并存導(dǎo)致的問(wèn)題,也消除了常見的內(nèi)存泄漏現(xiàn)象。

內(nèi)存管理

雖然 JS 有自動(dòng)的垃圾回收機(jī)制

但是為了確保占用最少的內(nèi)存讓頁(yè)面獲得更好的性能。而優(yōu)化內(nèi)存占用的最佳方式,就是執(zhí)行中的代碼只保存必要的數(shù)據(jù)。一旦數(shù)據(jù)不再有用,最好通過(guò)將其值設(shè)置為 null 來(lái)釋放其引用——這個(gè)做法叫做 解除引用

解除引用的方式適合用在全局變量下,因?yàn)榫植孔兞繒?huì)在函數(shù)執(zhí)行完畢后被自動(dòng)解除引用。

不過(guò),解除一個(gè)值的引用并不意味著自動(dòng)回收該值所占用的內(nèi)存。解除引用的真正作用是讓值脫離執(zhí)行環(huán)境,以便垃圾收集器下次運(yùn)行時(shí)將其回收。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容