|
一、垃圾回收機(jī)制的必要性 由于字符串、對(duì)象和數(shù)組沒(méi)有固定大小,所以當(dāng)它們的大小已知時(shí),才能對(duì)它們進(jìn)行動(dòng)態(tài)的存儲(chǔ)分配。JavaScript程序每次創(chuàng)建字符串、數(shù)組或?qū)ο髸r(shí),解釋器都必須分配內(nèi)存來(lái)存儲(chǔ)那個(gè)實(shí)體。只要像這樣動(dòng)態(tài)地分配了內(nèi)存,最終都要釋放這些內(nèi)存以便它們能夠被再用,否則,JavaScript的解釋器將會(huì)消耗完系統(tǒng)中所有可用的內(nèi)存,造成系統(tǒng)崩潰。 JavaScript的解釋器可以檢測(cè)到何時(shí)程序不再使用一個(gè)對(duì)象了,當(dāng)它確定了一個(gè)對(duì)象是無(wú)用的時(shí)候,它就知道不再需要這個(gè)對(duì)象,可以把它所占用的內(nèi)存釋放掉了。 二、垃圾回收機(jī)制 Js具有自動(dòng)垃圾回收機(jī)制。垃圾收集器會(huì)按照固定的時(shí)間間隔周期性的執(zhí)行。 1、標(biāo)記清除(常用) 當(dāng)一塊內(nèi)存中的數(shù)據(jù)能夠被訪問(wèn)時(shí),垃圾回收器就認(rèn)為"該數(shù)據(jù)能夠被獲得"。不能夠被獲得的數(shù)據(jù),就會(huì)被打上標(biāo)記,并回收內(nèi)存空間。這種方式叫作標(biāo)記---清除算法。 這個(gè)算法會(huì)設(shè)置一個(gè)全局對(duì)象,并定期地從全局對(duì)象開(kāi)始查找,垃圾回收器會(huì)找到所有可以獲得與不能獲得的數(shù)據(jù)。 工作流程: ?。?)垃圾回收器,在運(yùn)行的時(shí)候會(huì)給存儲(chǔ)在內(nèi)存中的所有變量都加上標(biāo)記。 (2)去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標(biāo)記。 (3)再被加上標(biāo)記的會(huì)被視為準(zhǔn)備刪除的變量。 ?。?)垃圾回收器完成內(nèi)存清除工作,銷(xiāo)毀那些帶標(biāo)記的數(shù)據(jù)并回收它們所占用的內(nèi)存空間。 注意:在局部作用域中,當(dāng)函數(shù)執(zhí)行完畢后,局部變量也就沒(méi)有存在的必要了,因此垃圾收集器很容易做出判斷并回收。但在全局中,變量什么時(shí)候需要自動(dòng)釋放內(nèi)存空間則很難判斷,因此我們?cè)陂_(kāi)發(fā)時(shí),應(yīng)盡量避免使用全局變量。如果使用了全局變量,則建議不再使用它時(shí),通過(guò)釋放變量方式,以確保能夠及時(shí)回收內(nèi)存空間。 2、引用計(jì)數(shù) 跟蹤記錄每個(gè)值被引用的次數(shù)。例當(dāng)變量聲明,第一次賦值時(shí)記為1,然后當(dāng)這個(gè)變量值改變時(shí),記錄為0,將計(jì)數(shù)為0的回收。 工作流程: (1)聲明了一個(gè)變量并將一個(gè)引用類(lèi)型的值賦值給這個(gè)變量,這個(gè)引用類(lèi)型值的引用次數(shù)就是1。 ?。?)同一個(gè)值又被賦值給另一個(gè)變量,這個(gè)引用類(lèi)型值的引用次數(shù)加1. (3)當(dāng)包含這個(gè)引用類(lèi)型值的變量又被賦值成另一個(gè)值了,那么這個(gè)引用類(lèi)型值的引用次數(shù)減1. (4)當(dāng)引用次數(shù)變成0時(shí),說(shuō)明沒(méi)辦法訪問(wèn)這個(gè)值了。 (5)當(dāng)垃圾收集器下一次運(yùn)行時(shí),它就會(huì)釋放引用次數(shù)是0的值所占的內(nèi)存。 但是當(dāng)循環(huán)引用的時(shí)候就會(huì)釋放不掉內(nèi)存。 1 function problem() {2 var objA = new Object();3 var objB = new Object();4 5 objA.someOtherObject = objB;6 objB.anotherObject = objA;7 }當(dāng)objA和objB通過(guò)各自的屬性相互引用,也就是說(shuō)這兩個(gè)對(duì)象的引用次數(shù)都是2。在采用引用計(jì)數(shù)的策略中,由于函數(shù)執(zhí)行之后,這兩個(gè)對(duì)象都離開(kāi)了作用域,函數(shù)執(zhí)行完成之后,objA和objB還將會(huì)繼續(xù)存在,因?yàn)樗麄兊囊么螖?shù)永遠(yuǎn)不會(huì)是0。這樣的相互引用如果說(shuō)很大量的存在就會(huì)導(dǎo)致大量的內(nèi)存泄露。 因?yàn)镮E中的BOM、DOM的實(shí)現(xiàn)使用了COM,而COM對(duì)象使用的垃圾收集機(jī)制是引用計(jì)數(shù)策略。所以會(huì)存在循環(huán)引用的問(wèn)題。 解決:手工斷開(kāi)js對(duì)象和DOM之間的鏈接,賦值為null。IE9把DOM和BOM轉(zhuǎn)換成真正的JS對(duì)象了,所以避免了這個(gè)問(wèn)題。 |
|
|
來(lái)自: 小仙女本仙人 > 《待分類(lèi)》