JavaScript學習 3、變量、做用域和內存

javascript的變量和C、java相去甚遠,按照《畫家與黑客》的說法,弱類型的變量是強大語言的基礎;做用域與其餘語言相似,但沒有塊級做用域;內存管理就要靠大學學的操做系統那門課的基礎了;看來當時學的時候不知道有什麼用,沒準到哪天就豁然開朗了,因此知識儲備仍是必不可少的。javascript

變量

ECMAScript變量包括兩種類型:基本類型和引用類型前端

基本類型是指簡單的數據段(Undefined、Null、Boolean、Number、String),引用類型是指那些可能由多個值構成的對象(Object)。java

這兩種類型的區別是:基本類型操做的是保存在變量中的實際的值,在傳遞參數或複製變量的時候,直接把變量值傳遞給參數。而引用類型的值是保存在內存中的對象,傳遞參數或複製變量時傳遞的是指針。算法

String類型在其餘語言中通常被當作對象,而在Javascript中是基本類型。瀏覽器

ECMAScript中傳遞參數的時候要注意引用的傳遞,其實是把指針的內容傳遞給參數。參數指針變化時,不影響原引用。參數操做指向的內容時,原引用同步變化。app

function setName(obj){
    obj.name="JavaScript";
    obj = new Object();    //參數的內容發生變化
    obj.name="React";
    
}

var person=new Object();
setName(person);
console.log(person.name);  //返回JavaScript/

 

實際上Java語言也是如此處理的:ide

public class JavaArguments{

    public static void main(String[] args){
        StringBuffer temp = new StringBuffer();
        temp.append("hello");

        test(temp);
        System.out.println(temp.toString());  //返回java
    }

    public static void test(StringBuffer sb){
        sb.append(" java");
        sb=new StringBuffer();
        sb.append("new StringBuffer");
    }
}

 

變量類型的檢測能夠是用typeof操做符,可是對於引用類型,只能返回object字符串,若是想知道對象的類型,則須要instanceof操做符,正確則返回true,不然返回false。函數

console.log(person instanceof Object);
console.log(person instanceof Array);
console.log(person instanceof RegExp);

 

執行環境及做用域

 執行環境(execution context)是JavaScript中最爲重要的一個概念。執行環境定義了變量或函數有權訪問的其餘數據,決定了他們各自的行爲。每一個執行環境都有一個與之關聯的變量對象(variable object)。spa

全局執行環境是最外圍的一個執行環境。根據宿主環境不一樣,表示執行環境的對象也不同。在Web瀏覽器中,全局執行環境被認爲是window對象,所以全部全局變量和函數都做爲window對象的屬性和方法建立的。操作系統

某個執行環境中全部代碼執行完畢後,該環境被銷燬,保存在其中的全部變量和函數定義也隨之銷燬(全局執行環境知道應用程序退出--例如關閉網頁或瀏覽器--時才被銷燬)。

每個函數都有本身的執行環境,當執行流進入一個函數時,函數的環境就會被推入一個環境棧中,而在環境執行後,棧將其環境彈出,把控制權返還給以前的執行環境。

當代碼在環境中執行時,會建立變量對象的一個做用域鏈(scope chain)。自身所在環境的變量對象是鏈條的前端,末端始終是全局環境的變量對象。若是一直找不到標識符,則會發生錯誤。

var color="blue";
function changeColor(){
    var anotherColor = "red";

    function swapColors(){
        var tempColor = anotherColor;
        anotherColor = color;
        color = tempColor;
        console.log("--------- 1-----------------")
        console.log(color);               //red
        console.log(anotherColor);  //blue
        console.log(tempColor);      //red
    }

    swapColors();
    console.log("--------- 2-----------------")
    console.log(color);                     //red
    console.log(anotherColor);        //blue
    //console.log(tempColor);          //undefined錯誤
}


changeColor();
console.log("--------- 3-----------------")
console.log(color);                        //red
//console.log(anotherColor);         //undefined錯誤
//console.log(tempColor);             //undefined錯誤
做用域鏈

with語句實際上就是指定了做用域鏈的前端。

 JavaScript中沒有塊級做用域,因此for語句中聲明的變量,在塊的外部同樣可以訪問。

垃圾回收

 JavaScript具備自動垃圾回收機制

針對局部變量,局部變量只在函數執行的過程當中存在,在棧(或堆)的頂部分配相應的空間,存儲它們的值,函數執行結束後,變量也就沒用了,此時便可釋放內存。

判斷變量是否有用的策略可能會因實現而異。

具體到瀏覽器,一般採用標記清除(mark-and-sweep)策略。

垃圾收集器在運行時會給存儲在內存中的全部變量都加上標記,而後他會去掉環境中的變量以及被環境的變量引用的變量的標記。至此仍然有標記的變量將被視爲準備刪除的變量,由於環境中的變量已經沒法訪問到這些變量了。最後垃圾收集器完成內存清除工做。銷燬那些帶標誌的值並回收他們所佔用的內存空間。

做爲開發人員,咱們可以作的,是在全局變量和全局對象再也不使用後,將其值設置位null來釋放引用。這個作法叫作 解除引用(dereferencing)。

小結

 JavaScript變量能夠用來保存兩種類型的值:基本類型值(Undefined、Null、Boolean、Number和String)和引用類型值。特色以下:

  • 基本類型值在內存中佔據固定大小的空間,所以被保存在棧空間中。
  • 從一個變量向另外一個變臉複製基本類型的值,會建立這個值的副本。
  • 引用類型的值是對象,保存在堆內存中。
  • 包含引用類型值的變量實際上包含的並非對象自己,而是指向該對象的指針。
  • 從一個變量向另外一個變量複製引用類型的值,複製的實際上是指針,所以兩個變量最終都指向同一個對象。
  • 能夠用typeof來判斷一個值哪一種基本類型,而肯定一個值是哪一種引用類型可使用instanceof操做符。

關於執行環境:

  • 執行環境有全局執行環境和函數執行環境之分。
  • 每次進入一個新的執行環境,都會建立一會用於搜索變量和函數的做用域鏈。
  • 函數的局部環境不只有全訪問函數做用域中的變量,並且有圈訪問其包含環境,乃至全局環境。
  • 全局環境只能訪問在全局環境中定義的變量和函數,而不能直接訪問局部環境中的任何數據。
  • 變量的執行環境有助於肯定應該什麼時候釋放內存。

關於內存管理:

  • 離開做用域的值將被標記位可回收,所以將在垃圾收集期間被刪除。
  • 「標記清除」是目前主流的垃圾收集算法,這種算法的思想是給當前不使用的值加上標記,而後再回收其內存。
  • 接觸變量的引用不只有助於消除循環引用現象,並且對垃圾收集也有好處。爲了確保有效地回收內存,應該及時解除再也不使用的全局對象、全局對象屬性以及循環引用變量的引用。

 

 

 

 

變量

 

變量

相關文章
相關標籤/搜索