JavaScript語言是一門優秀的指令碼語言。其中包含指令碼語言的靈活性外還擁有許多進階語言的特性。例如充許構建和執行個體化一個對象,記憶體回收機制(GC:Garbage Collecation)。通常我們使用new建立對象,GC負責回收對象佔用記憶體地區。因此瞭解GC,可以加深對javascript記憶體回收機制的理解。
GC在回收記憶體時,首先會判斷該對象是否被其它對象引用。在確定沒有其它對象引用便釋放該對象記憶體地區。因此如何確定對象不再被引用是GC的關鍵所在。
<script type="text/javascript">
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>
如上代碼中,執行完cc()後a1被回收了,此後我們可以通過b1.rr彈出文字視窗。在一些基礎書籍中解釋為:a1為局部變數,b1是全域變數。局部變數執行完後會被GC回收.但不全是這樣,如下代碼:
<script type="text/javascript">
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>
此時cc函數中的 a1,b1都是局部變數,但仍然會彈出文字視窗。說明b1並沒有被GC回收。因此javascript中局部變數不是所有時候都被GC回收的。
GC回收機制還需要近一步瞭解。在此時引入幾個概念:雙向鏈表,範圍鏈,使用中的物件(為了方便理解,簡化了原文的概念[http://softbbs。pconline。com。cn/9497825。html]) , 其中雙向鏈表描述複雜物件的上下層級關係。 範圍鏈與使用中的物件分別是雙向鏈表中的某個節點。以函數cc為例變數層級關係為:
window<=>cc<=>a1<=>rr
<=>b1<=>rr
在執行cc()方法時,記憶體中變數的參考關聯性如,文字解釋如下:
- cc的使用中的物件包括a1和b1,其範圍鏈是window
- cc的使用中的物件包括a1和b1,其範圍鏈是window
- a1的使用中的物件包括rr,其範圍鏈是cc
- b1的使用中的物件包括rr,其範圍鏈是cc
執行cc()時,cc的執行環境會建立一個使用中的物件和一個範圍鏈。其局部變數a1,b1都會掛在cc的使用中的物件中。當cc()執行完畢後,執行環境會嘗試回收使用中的物件佔用的記憶體。但因局部變數b1 通過return b1,為其增加了一條範圍鏈:window<=>b1<=>rr,所以GC停止對b1回收。因此如果想將一個局部變數/函數提升為全域的,為其增加一條範圍鏈就OK了。
同時控制好對象的範圍鏈也變得重要了。因範圍鏈會意外導致GC無法回收目標對象。例如:
<SCRIPT LANGUAGE="JavaScript">
<!--
//貓
function cat(name)
{
var zhuren ;
this.name = name;
//設定主人
this.addZhuRen = function(zr){
zhuren = zr;
}
this.getZhuRen = function(){
return zhuren;
}
}
//主人
function zhuren(name){
this.name = name;
}
//建立主人:
var zr = new zhuren("zhangsan");
//建立貓
var cat1 = new cat("asan");
//設定該貓的主人
cat1.addZhuRen(zr);
//釋放主人
zr = null ;
//此處還存在對主人對象的引用
alert(cat1.getZhuRen().name)
//-->
</SCRIPT>