概述
JS的垃圾回收機(jī)制是為了以防內(nèi)存泄漏,內(nèi)存泄漏的含義就是當(dāng)已經(jīng)不需要某塊內(nèi)存時(shí)這塊內(nèi)存還存在著,垃圾回收機(jī)制就是間歇的不定期的尋找到不再使用的變量,并釋放掉它們所指向的內(nèi)存。
C#、Java、JavaScript有自動(dòng)垃圾回收機(jī)制,但c++和c就沒(méi)有垃圾回收機(jī)制,也許是因?yàn)槔厥諜C(jī)制必須由一種平臺(tái)來(lái)實(shí)現(xiàn)。在JS中,JS的執(zhí)行環(huán)境會(huì)負(fù)責(zé)管理代碼執(zhí)行過(guò)程中使用的內(nèi)存
2.變量的生命周期
當(dāng)一個(gè)變量的生命周期結(jié)束之后它所指向的內(nèi)存就應(yīng)該被釋放。JS有兩種變量,全局變量和在函數(shù)中產(chǎn)生的局部變量。局部變量的生命周期在函數(shù)執(zhí)行過(guò)后就結(jié)束了,此時(shí)便可將它引用的內(nèi)存釋放(即垃圾回收),但全局變量生命周期會(huì)持續(xù)到瀏覽器關(guān)閉頁(yè)面。
JS垃圾回收方式
JS執(zhí)行環(huán)境中的垃圾回收器怎樣才能檢測(cè)哪塊內(nèi)存可以被回收有兩種方式:標(biāo)記清除(mark and sweep)、引用計(jì)數(shù)(reference counting)。
3.1 標(biāo)記清除
這是javascript中最常用的垃圾回收方式。當(dāng)變量進(jìn)入執(zhí)行環(huán)境是,就標(biāo)記這個(gè)變量為“進(jìn)入環(huán)境”。從邏輯上講,永遠(yuǎn)不能釋放進(jìn)入環(huán)境的變量所占用的內(nèi)存,因?yàn)橹灰獔?zhí)行流進(jìn)入相應(yīng)的環(huán)境,就可能會(huì)用到他們。當(dāng)變量離開(kāi)環(huán)境時(shí),則將其標(biāo)記為“離開(kāi)環(huán)境”。
垃圾收集器在運(yùn)行的時(shí)候會(huì)給存儲(chǔ)在內(nèi)存中的所有變量都加上標(biāo)記。然后,它會(huì)去掉環(huán)境中的變量以及被環(huán)境中的變量引用的標(biāo)記。而在此之后再被加上標(biāo)記的變量將被視為準(zhǔn)備刪除的變量,原因是環(huán)境中的變量已經(jīng)無(wú)法訪問(wèn)到這些變量了。最后。垃圾收集器完成內(nèi)存清除工作,銷毀那些帶標(biāo)記的值,并回收他們所占用的內(nèi)存空間。
3.2 引用計(jì)數(shù)
所謂"引用計(jì)數(shù)"是指語(yǔ)言引擎有一張"引用表",保存了內(nèi)存里面所有的資源(通常是各種值)的引用次數(shù)。如果一個(gè)值的引用次數(shù)是0,就表示這個(gè)值不再用到了,因此可以將這塊內(nèi)存釋放。
4 內(nèi)存泄漏
4.1 意外的全局變量
比如 function(){ bar = '小豬' } 這里bar就沒(méi)有被聲明會(huì)變成一個(gè)全局的變量,再頁(yè)面關(guān)閉之前不會(huì)被釋放,還有
function foo(){
this.name = '小豬'
}
foo()
這種自己調(diào)用自己的也會(huì)this指向了全局對(duì)象 window
4.2 被遺忘的計(jì)時(shí)器或回調(diào)函數(shù)
計(jì)時(shí)器或者回調(diào)函數(shù)中使用了某個(gè)上面的變量。但是結(jié)束后計(jì)時(shí)器和回調(diào)函數(shù)沒(méi)有被清除,那么他所使用的上面的變量也會(huì)一直被引用,從而不被垃圾回收機(jī)制所收回。
4.3 閉包
閉包可以維持函數(shù)內(nèi)局部變量,使其得不到釋放。
解決方式:將時(shí)間處理函數(shù)定義在外部,解除閉包,或者在定義事件處理函數(shù)的外部函數(shù)中,清除原本聲明的變量。
4.4 沒(méi)有清理的DOM元素引用
如果顯示在某個(gè)地方,用document獲取某個(gè)DOM元素,并且賦給某個(gè)值,就算是下面你在h5的頁(yè)面中把那個(gè)節(jié)點(diǎn)給移除了,但是你的js代碼中還是有這個(gè)dom,換而言之,DOM元素還存在內(nèi)存里面。
5 內(nèi)存泄漏的識(shí)別方法
步驟:打開(kāi)開(kāi)發(fā)者工具 Performance
勾選 Screenshots 和 memory
左上角小圓點(diǎn)開(kāi)始錄制(record)
停止錄制
圖中 Heap 對(duì)應(yīng)的部分就可以看到內(nèi)存在周期性的回落也可以看到垃圾回收的周期,如果垃圾回收之后的最低值(我們稱為min),min在不斷上漲,那么肯定是有較為嚴(yán)重的內(nèi)存泄漏問(wèn)題。
6 避免內(nèi)存泄漏的一些方法
減少不必要的全局變量,或者生命周期較長(zhǎng)的對(duì)象,及時(shí)對(duì)無(wú)用的數(shù)據(jù)進(jìn)行垃圾回收。
注意程序的邏輯,避免死循環(huán)之類的
避免創(chuàng)建過(guò)多的對(duì)象
總而言之,不用的東西要及時(shí)的歸還
7 垃圾回收的使用場(chǎng)景優(yōu)化
7.1 數(shù)組array的優(yōu)化
arr = [],這種方式雖然把原來(lái)的給釋放了,但是又創(chuàng)建了一個(gè)新的空對(duì)象,實(shí)際上,將數(shù)組的長(zhǎng)度賦值為0,arr.length = 0 能夠達(dá)到清空數(shù)組的目的,并實(shí)現(xiàn)了數(shù)組的重用,減少內(nèi)存垃圾的產(chǎn)生.
7.2 在循環(huán)的函數(shù)表達(dá)式,能復(fù)用的最好放在外面
// 在循環(huán)中最好也別使用函數(shù)表達(dá)式。
for (var k = 0; k < 10; k++) {
var t = function(a) {
// 創(chuàng)建了10次 函數(shù)對(duì)象。
console.log(a)
}
t(k)
}
寫成
// 推薦用法
function t(a) {
console.log(a)
}
for (var k = 0; k < 10; k++) {
t(k)
}
t = null
總結(jié)參考:https://juejin.im/post/5cb33660e51d456e811d2687
最后編輯于 :2020.03.31 13:58:52
?著作權(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ù)。