JavaScript的環境與內存

使用具備垃圾收集機制語言編寫程序,開發人員一般不必操心內存管理的問題。但是,JavaScript在進行內存管理即垃圾收集時面臨的問題還是有點與衆不同。其中最主要的一個問題,就是分配給Web瀏覽器的可用內存數量通常要比分配給桌面應用程序的少。確保佔有最少的內存可以讓頁面獲得更好的性能,而優化內存佔有最佳方式,就是爲執行的代碼值保存必要的數據。

 

基本類型值和引用類型值

 

ECMAScript變量包含兩種不同數據類型的值:基本類型值和引用類型值。基本類型值保存在棧內存中,而引用類型值保存在堆內存中。

5種基本類型Undefined、Null、Boolean、Number、String,它們的值在內存中分別佔有固定大小的空間,因此可以把它們的值保存在棧內存中,也可以提高查詢變量的速度,對於它們可以說是按值訪問的。

如果是引用類型的值,則必須在堆內存中分配空間。因爲它們的值大小不固定,因此不能保存在棧內存中,但內存地址的大小是固定的,所以可以將內存地址保存在棧內存中,再根據地址找到保存在堆中的值,這種查詢方式叫做按引用訪問。

 

動態屬性

 

對於引用類型的值,可以爲其添加屬性和方法,也可以改變和刪除其屬性和方法,例如:

 

var myobj = new Object();

myobj.name = "obj";

alert(myobj.name);

 

但是不能給基本類型的值添加屬性,例如:

 

var mystr = "string";

mystr.name = "str";

alert(mystr.name); //undefined

 

複製變量值

 

如果從一個變量向另一個變量複製基本類型的值,會在棧中創建一個新值,然後把該值複製到爲新變量分配的位置上,例如:

 

var num1 = 5;

var num2 = num1;

 

如果從一個變量向另一個變量複製引用類型的值,同樣會將存儲在棧中的值複製一份放到爲新變量分配的空間中。但是這個值的副本實際是指向存儲在堆中的一個對象的指針,例如:

 

var myobj1 = new Object();

var myobj2 = myobj1;

myobj1.name = "obj";

alert(myobj2.name); //obj

 

傳遞參數

 

ECMAScript中所有函數參數都是按值傳遞的。在向參數傳遞基本類型的值時,被傳遞的值會被複制給一個局部變量,在向參數傳遞引用類型的值時,會把這個值在內存中的地址複製給一個局部變量。

使用基本類型值傳遞參數比較簡單,例如:

 

function add(num) {

  num+= 10;

 return num;

}

var number = 20;

var result = add(number);

alert(number); //20

alert(result); //30

 

如果使用引用類型值則稍複雜,例如:

 

function setName(obj) {

 obj.name = "obj";

}

var myobj = new Object();

setName(myobj);

alert(myobj.name); //obj

 

但這並不表明局部作用域中修改的對象會在全局作用域中反映出來,對象仍然是按值(內存地址)傳遞的,例如:

 

function setName(obj) {

 obj.name = "obj";

  obj= new Object();

 obj.name = "new obj";

}

var myobj = new Object();

setName(myobj);

alert(myobj.name); //obj

 

檢測類型

 

typeof操作符可以檢測一個變量是哪種基本類型,但在檢測引用類型時,總是返回object。通常我們並不是想知道某個值是對象,而是想知道它是什麼類型的對象,可以使用instanceof操作符,語法如下:

 

result = variable instanceof constructor

 

如果變量是給定引用類型的實例,那麼instanceof操作符就會返回true。根據規定,所有引用類型的值都是Object的實例。

 

環境與作用域

 

執行環境定義了變量或函數有權訪問的其他數據,每個執行環境都有一個與之關聯的變量對象,環境中定義的所有變量和函數都保存在這個對象中。這個對象無法訪問,但解析器會在後臺使用它。全局執行環境是最外圍的一個執行環境,在Web瀏覽器中,全局執行環境被認爲是window對象。某個執行環境中的所有代碼執行完畢後,該環境被銷燬,保存在其中的所有變量和函數定義也隨之銷燬。

 

當代碼在一個環境中執行時,會創建由變量對象構成的一個作用域鏈,保證對執行環境有權訪問的所有變量和函數的有序訪問。全局執行環境是作用域鏈中的最後一環,標識符解析是沿着作用域鏈一級級搜索,從作用域鏈接前端(當前執行環境)開始,直到找到標識符爲止。

 

作用域鏈的延長

 

有些語句可以在作用域鏈的前端臨時增加一個變量對象,該變量對象會在代碼執行後被移除,即當執行流進入下列任何一個語句時,作用域鏈就會得到加長:

 

 try-cache語句的catch塊。

 with語句。

 

塊級作用域

 

JavaScript沒有塊級作用域,即花括號封閉的代碼塊中定義的變量可以在代碼塊外訪問,例如:

 

if (true) {

  varcolor = "blue";

}

alert(color);

 

變量聲明

 

在使用var關鍵字聲明變量時,這個變量將被自動添加到距離最近的可用環境中。如果變量在未經聲明的情況下被初始化,那麼該變量會被自動添加到全局環境。

 

本文爲Anyforweb技術分享博客,需要了解網站建設及更多web應用相關信息,請訪問anyforweb.com。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章