js垃圾回收機制和內(nèi)存泄露那些事

一、內(nèi)存垃圾回收的意義:

????????在不需要字符串闻察、對象的時候拱礁,要釋放其所占的內(nèi)存琢锋,否則系統(tǒng)中的內(nèi)存有限,占用太多會造成系統(tǒng)奔潰呢灶。

二吴超、垃圾回收的機制:

????????js會自動回收垃圾內(nèi)存。

????????垃圾回收:找出那些不再繼續(xù)使用的變量鸯乃,釋放其占用的內(nèi)存鲸阻。

????????js會按照固定的時間間隔周期性的執(zhí)行垃圾回收的操作。

????????全局變量的的生命周期會知道瀏覽器關(guān)閉結(jié)束缨睡,也就是說全局變量不會被當成垃圾回收鸟悴。

三、怎么回收:標記清除奖年、引用計數(shù)细诸。

????????1) 標記清除? (變量)

????????????????目前最常用的垃圾回收機制,也是當前瀏覽器才用的機制陋守。

????????????????原理:

????????????????標記清除中有兩個重要的概念“進入環(huán)境”震贵、“離開環(huán)境”∷溃“進入環(huán)境”:是變量進入執(zhí)行環(huán)境猩系,“離開環(huán)境”:是變量完成任務,離開執(zhí)行環(huán)境中燥。

????????????????當聲明一個變量時寇甸,這個變量就是進入的執(zhí)行環(huán)境,瀏覽器給加“進入環(huán)境”的標記褪那,當離開執(zhí)行環(huán)境時幽纷,瀏覽器給它加“離開環(huán)境”的標記。并且回收博敬。

????????????????流程:

????????????????1. 垃圾收集器在運行的時候給所有內(nèi)存中的變量打上標記友浸。

????????????????2. 去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標記。

????????????????3. 那些還存在標記的變量則被視為準備刪除的變量偏窝。

????????????????4. 最后垃圾收集器會執(zhí)行清除內(nèi)存的工作收恢,銷毀那些帶標記的值并回收他們占用的內(nèi)存。

????????2) 引用計數(shù)

????????????????跟蹤記錄每個值的引用次數(shù)? (值)

????????????????流程:

????????????????1. 聲明一個變量祭往,并給這個變量賦值伦意,這個值的引用次數(shù)就是1

????????????????2. 同一個值被賦給另一個變量,這個值的引用次數(shù)+1

????????????????3. 變量的值被更改了 那原本那個值的引用次數(shù)-1

????????????????4. 引用次數(shù)為0時硼补,說明沒辦法訪問這個值了

????????????????5. 垃圾收集器下一次運行時驮肉,會釋放引用次數(shù)為0的值所占的內(nèi)存

????????????????這個流程潛在一個問題:循環(huán)引用,則引用次數(shù)不會為0已骇,將不能被自動回收了离钝。

????????????????循環(huán)引用:是指A中包含指向?qū)ο驜的指針票编,而對象B中也包含一個指向?qū)ο驛的引用。

? ????????????????Eg.

? ???????????????????? function ftc(){

? ???????????????????????? var A = new Object();

? ???????????????????????? var B = new Object();

? ???????????????????????? A.property = B;

? ???????????????????????? B.property = A;

? ???????????????????? }

四卵渴、內(nèi)存泄露的原因

????????js雖然有自動回收機制慧域,但是還是有些情況會造成內(nèi)存泄漏:

????????1. 全局變量不會被自動回收

????????????????function foo(){

????????????????????this.bar2 = "默認綁定this指向全局"? //全局變量 == window.bsr2

????????????????????bar = "全局變量"? // 沒有var聲明的變量也是全局變量 == window.bar

????????????????}

????????????????foo();

????????????????解決辦法:在函數(shù)內(nèi)使用嚴格模式or細心一點

????????????????function foo(){

????????????????????"use strict"

????????????????????this.bar2 = "默認綁定this指向全局"? //全局變量 == window.bsr2

????????????????????bar = "全局變量"? // 沒有var聲明的變量也是全局變量 == window.bar

????????????????}

????????????????foo();

2. 當不需要setInterval或者setTimeout時,定時器沒有被清除浪读。定時器的回調(diào)函數(shù)以及內(nèi)部依賴的變量都不能被回收昔榴,造成內(nèi)存泄露。

var someResource = getData();

setInterval(function(){

var node = document.getElementById("id");

if(node){

node.innerHTML = JSON.stringify(someResource);

//定時器也沒有被清除

}

// node碘橘、someResource 存儲了大量數(shù)據(jù) 無法回收

},1000)

解決辦法:定時器結(jié)束時互订,手動清除定時器。

3. 循環(huán)引用蛹屿,上文提到屁奏。

? 解決辦法:手動清除變量岩榆,釋放內(nèi)存错负。

4. 沒有清除的DOM元素引用

var refV = document.getElementById("ID");

document.body.removeChild(refV);//頁面上dom刪除了

console.log(refV);//能輸出值。所以雖然在頁面上dom刪除了勇边,但在js中 這個dom的變量還在 沒有被回收

refV = null;//解決辦法 手動清除

console.log(refV);//可以看到已經(jīng)被清除了

5. 閉包引起的內(nèi)存泄漏:閉包實際上非常容易造成JavaScript對象和DOM對象的隱蔽循環(huán)引用

? 解決辦法:將事件處理函數(shù)定義在外部犹撒,解除閉包;或者在定義事件處理函數(shù)的外部函數(shù)中粒褒,刪除對dom的引用,手動回收识颊。

? Eg.1? ?

? function ex(){

? var element = document.getElementById("div1");? // 1

? element.onclick = function(){

? console.log("this is event"); // 2

? }

? }

? ex();


? 以上函數(shù)ex中,用匿名函數(shù)創(chuàng)建了一個閉包

? 第1處:js對象 element 引用了一個dom對象? ? JS(element) ----> DOM(div1)

? 第2處:dom對象的onclick屬性引用了一個匿名函數(shù)奕坟,這形成一個閉包祥款,這個匿名函數(shù)可以引用整個ex內(nèi)的所有對象,包括element DOM(div1.onclick) ---->JS(element)

? 由此形成了JavaScript對象和DOM對象的隱蔽循環(huán)引用月杉。

? 解決辦法:

? function ex(){

? var element = document.getElementById("div1");? // 1

? element.onclick = function(){

? console.log("this is event"); // 2

? }

? element = null; //添加的語句 刪除對dom的引用,手動回收

? }

Eg.2

function ev(){

var element = document.getElementById("div2")

var myName = "lili"

element.onclick = function(){

console.log(myName)

}

}

ev();

由于js中只有函數(shù)才具有獨立的作用域刃跛。

以上函數(shù)ev中,onclick引用的匿名函數(shù)去訪問myName的時候苛萎,發(fā)現(xiàn)自身作用域中沒有這個myName變量桨昙,

所以需要去訪問父作用域中去調(diào)用這個myName變量,形成了閉包腌歉,所以myName這個變量會一直存在蛙酪。

myName這個變量在onclick事件運行之后還會頑固的存在在內(nèi)存中。

解決辦法是運行完成后手動清除 myName = null

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末翘盖,一起剝皮案震驚了整個濱河市桂塞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌馍驯,老刑警劉巖阁危,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炊甲,死亡現(xiàn)場離奇詭異,居然都是意外死亡欲芹,警方通過查閱死者的電腦和手機卿啡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來菱父,“玉大人颈娜,你說我怎么就攤上這事≌阋耍” “怎么了官辽?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長粟瞬。 經(jīng)常有香客問我同仆,道長,這世上最難降的妖魔是什么裙品? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任俗批,我火速辦了婚禮,結(jié)果婚禮上市怎,老公的妹妹穿的比我還像新娘岁忘。我一直安慰自己,他們只是感情好区匠,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布干像。 她就那樣靜靜地躺著,像睡著了一般驰弄。 火紅的嫁衣襯著肌膚如雪麻汰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天戚篙,我揣著相機與錄音五鲫,去河邊找鬼。 笑死已球,一個胖子當著我的面吹牛臣镣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播智亮,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼忆某,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤坡慌,失蹤者是張志新(化名)和其女友劉穎斜脂,沒想到半個月后聋呢,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苗踪,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年削锰,在試婚紗的時候發(fā)現(xiàn)自己被綠了通铲。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡器贩,死狀恐怖颅夺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蛹稍,我是刑警寧澤吧黄,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站唆姐,受9級特大地震影響拗慨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜奉芦,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一赵抢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧仗阅,春花似錦昌讲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽车吹。三九已至筹裕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窄驹,已是汗流浹背朝卒。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留乐埠,地道東北人抗斤。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像丈咐,于是被迫代替她去往敵國和親瑞眼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

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