javascript 內(nèi)存回收機(jī)制理解
javascript語言是一門優(yōu)秀的腳本語言.其中包含腳本語言的靈活性外還擁有許多高級語言的特性.例如充許構(gòu)建和實(shí)例化一個(gè)對象,垃圾回收機(jī)制(GC:Garbage Collecation).通常我們使用new創(chuàng)建對象,GC負(fù)責(zé)回收對象占用內(nèi)存區(qū)域.因此了解GC,可以加深對javascript垃圾回收機(jī)制的理解。
2.用局部變量和全局變量解釋GC
GC在回收內(nèi)存時(shí),首先會(huì)判斷該對象是否被其它對象引用.在確定沒有其它對象引用便釋放該對象內(nèi)存區(qū)域.因此如何確定對象不再被引用是GC的關(guān)鍵所在.
<script>
function aa(){
this.rr = "彈窗";
}
function bb(){
this.rr = "彈窗";
}
var b1;
function cc(){
var a1 = new aa();
b1 = new bb();
return b1;
}
cc();
alert(b1.rr)
</script>
如上代碼中,執(zhí)行完cc()后a1被回收了,此后我們可以通過b1.rr彈出文字窗口.在一些基礎(chǔ)書籍中解釋為:a1為局部變量,b1是全局變量.局部變量執(zhí)行完后會(huì)被GC回收.但不全是這樣,如下代碼:
<script>
function aa(){
this.rr = "彈窗";
}
function bb(){
this.rr = "彈窗";
}
function cc(){
var a1 = new aa();
var b1 = new bb();
return b1;
}
var b1 = cc();
alert(b1.rr);
</script>
此時(shí)cc函數(shù)中的 a1,b1都是局部變量,但仍然會(huì)彈出文字窗口.說明b1并沒有被GC回收.因此javascript中局部變量不是所有時(shí)候都被GC回收的.
3.抽象理解GC
GC回收機(jī)制還需要近一步了解。在此時(shí)引入幾個(gè)概念:雙向鏈表,作用域鏈,活動(dòng)對象(為了方便理解,簡化了原文的概念[http://softbbs.pconline.com.cn/9497825.html]) , 其中雙向鏈表描述復(fù)雜對象的上下層級關(guān)系. 作用域鏈與活動(dòng)對象分別是雙向鏈表中的某個(gè)節(jié)點(diǎn).以函數(shù)cc為例變量層級關(guān)系為:
window<=>cc<=>a1<=>rr
<=>b1<=>rr
(原文有詳細(xì)解釋)在執(zhí)行cc()方法時(shí),內(nèi)存中變量的引用關(guān)系如上圖,文字解釋如下:
window的活動(dòng)對象包括cc,假設(shè)window是頂級對象(因?yàn)檫\(yùn)行中不會(huì)被回收)
cc的活動(dòng)對象包括a1和b1,其作用域鏈?zhǔn)莣indow
a1的活動(dòng)對象包括rr,其作用域鏈?zhǔn)莄c
b1的活動(dòng)對象包括rr,其作用域鏈?zhǔn)莄c
執(zhí)行cc()時(shí),cc的執(zhí)行環(huán)境會(huì)創(chuàng)建一個(gè)活動(dòng)對象和一個(gè)作用域鏈.其局部變量a1,b1都會(huì)掛在cc的活動(dòng)對象中.當(dāng)cc()執(zhí)行完畢后,執(zhí)行環(huán)境會(huì)嘗試回收活動(dòng)對象占用的內(nèi)存.但因局部變量b1 通過return b1,為其增加了一條作用域鏈:window<=>b1<=>rr,所以GC停止對b1回收.
因此如果想將一個(gè)局部變量/函數(shù)提升為全局的,為其增加一條作用域鏈就OK了。
同時(shí)控制好對象的作用域鏈也變得重要了.因作用域鏈會(huì)意外導(dǎo)致GC無法回收目標(biāo)對象.例如:
<SCRIPT LANGUAGE="JavaScript">
<!--
//貓
function cat(name){
var zhuren ;
this.name = name;
//設(shè)置主人
this.addZhuRen = function(zr){
zhuren = zr;
}
this.getZhuRen = function(){
return zhuren;
}
}
//主人
function zhuren(name){
this.name = name;
}
//創(chuàng)建主人:
var zr = new zhuren("zhangsan");
//創(chuàng)建貓
var cat1 = new cat("asan");
//設(shè)置該貓的主人
cat1.addZhuRen(zr);
//釋放主人
zr = null ;
//此處還存在對主人對象的引用
alert(cat1.getZhuRen().name)
//-->
</SCRIPT>
相關(guān)文章
JS實(shí)現(xiàn)將圖片轉(zhuǎn)為base64格式
Base64是一種用64個(gè)字符來表示任意二進(jìn)制數(shù)據(jù)的方法,這篇文章主要為大家介紹了如何實(shí)現(xiàn)將圖片轉(zhuǎn)為base64格式,感興趣的小伙伴可以學(xué)習(xí)一下2023-07-07IE8利用自帶的setCapture和releaseCapture解決iframe的拖拽事件方法
最近有個(gè)需求須要實(shí)現(xiàn)左右拖拽功能,頁面右邊是個(gè)iframe頁面,在chrome測試通過之后,發(fā)現(xiàn)在ie8上面效果不是很理想,查閱相關(guān)資料找到可以使用ie自帶的setCapture和releaseCapture來解決,需要的朋友可以參考下2016-10-10微信小程序定義和調(diào)用全局變量globalData的實(shí)現(xiàn)
這篇文章主要介紹了微信小程序定義和調(diào)用全局變量globalData的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11javascript設(shè)置連續(xù)兩次點(diǎn)擊按鈕時(shí)間間隔的方法
這篇文章主要介紹了javascript設(shè)置連續(xù)兩次點(diǎn)擊按鈕時(shí)間間隔的方法,是非常實(shí)用的技巧,需要的朋友可以參考下2014-10-10Echarts基本用法_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Echarts基本用法,詳解的介紹了Echarts的基本用法和實(shí)例,有興趣的可以了解一下2017-08-08js實(shí)現(xiàn)頁面打印功能實(shí)例代碼(附去頁眉頁腳功能代碼)
js實(shí)現(xiàn)頁面打印功能實(shí)例代碼(附去頁眉頁腳功能代碼)2009-12-12前端項(xiàng)目中報(bào)錯(cuò)Uncaught?(in?promise)的解決方法
最近在做項(xiàng)目的時(shí)候控制臺(tái)報(bào)了一個(gè)錯(cuò)Uncaught(in promise) false,這篇文章主要給大家介紹了關(guān)于前端項(xiàng)目中報(bào)錯(cuò)Uncaught?(in?promise)的解決方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-049個(gè)讓JavaScript調(diào)試更簡單的Console命令
這篇文章主要為大家詳細(xì)介紹了9個(gè)讓JavaScript調(diào)試更簡單的Console命令,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11