天天看點

JavaScript權威指南__第三章

第三章:類型、值和變量

3.1~3.9lue

3.10:變量作用域

  • JavaScript中在函數内部定義的變量屬于

    局部變量

    隻在函數内部有定義;
  • 函數參數也是局部變量,隻在函數内有定義;
  • 在函數體内

    局域變量

    的優先級高于同名的全局變量,如果在一個函數内聲明一個局部變量或者函數參數中帶有的變量和全局變量重名,則全局變量被局部變量覆寫;
var scope = "global"; // 聲明一個全局變量
function checkscope() {
    var scope = "local"; // 聲明一個與全局變量同名的局部變量
    return scope;
}
checkscope(); // => "local"
           
  • 在全局作用域中定義變量時可以不使用

    var

    , 但聲明局部變量時必須使用

    var

    語句:
scope = "global"; // 聲明一個全局變量,可以不使用var來聲明
function checkscope2() {
    scope = "local"; // 此處不是聲明變量,而是修改了全局變量
    myscope = "local"; // 顯式的聲明一個新的全局變量
    return [scope, myscope]; // 傳回兩個值
}
checkscope2();  // => ["local", "local"]
           
  • 當嵌套的定義函數時,會出現局部作用域的嵌套情況:
var scope = "global scope"; // 全局變量
function checkscope() {
    var scope = "local scope"; // 局部變量
    function nested() {
        var scope = "nested scope"; // 嵌套作用域内的局部變量
        return scope;   // 傳回目前作用域内的值
    }
    return nested();
}
checkscope(); // => "嵌套作用域"
           

3.10.1:函數作用域和聲明提前

  • 函數作用域:JavaScript中沒有塊作用域,是以在if代碼塊或for代碼塊中聲明的變量在整個函數中都有定義,甚至可以在變量聲明前就可以使用
function test(o) {
    var i = o; // i在整個函數中都有定義
    if(typeof i == "object") {
        var j = ; // j在整個函數内都有定義,在j聲明之前也可以使用
        for(var k=; k<; k++) { // k在整個函數内部都有定義,同上;
            console.log(k); // 輸出0~9
        }
        console.log(k); // 此處k已經定義,輸出10
    }
    console.log(j); // j已經定義,但可能沒有初始化
}
           
  • 聲明提前:函數内部聲明的變量(包括if代碼塊和for代碼塊中)都被“提前”到函數體的頂部
var scope = "global";
function f() {
    console.log(scope); // 輸出undefined,不是“global”,因為下一行什麼的scope将全局變量scope覆寫掉,是以此處的scope是下面聲明的scope而不是上面的全局變量,但此時該局部變量尚未初始化,是以輸出undefined
    var scope = "local";// 變量在函數體内部都有定義
    console.log(scope); // 輸出local
}

// 以上代碼等價于下面的代碼
function f() {
    var scope; // 在函數頂部聲明了局部變量
    console.log(scope);// 變量存在,但未初始化,其值為“undefined”
    scope = "local";    // 此處将其初始化指派
    console.log(scope); // 輸出“local”
}
           

3.10.2:作為屬性的變量

  • 當聲明一個JavaScript全局變量時,實際上是定義了全局對象的一個屬性,當使用var聲明一個變量時,建立的這個屬性是不可比對的,即該變量無法通過delete運算符删除,如果沒有使用嚴格模式并給一個未聲明的變量指派的話,JavaScript會自動建立一個全局變量,這種方式建立的變量時全局對象的正常的可比對屬性,并可以删除;
var truevar = ;    // 聲明一個不可删除的全局變量
fakevar = ;        // 建立全局變量的一個可删除的屬性
this.fakevar2 = ;  // 同時
delete truevar;     // => false; 變量不可删除
delete fakevar;     // => true;變量被删除
delete this.fakevar2;// => true; 變量被删除
           
  • javascript 中全局變量就是全局對象的屬性,可以使用this關鍵字來引用全局對象;但是卻沒有辦法來引用存放局部變量的對象,這是通過不可見的内部實作的,但這種局部變量對象存在的觀念是非常重要的,見下一節.

3.10.3:作用域鍊

  • 全局變量在程式中始終都有定義的;
  • 局部變量在聲明它的函數體内以及其所嵌套的函數内始終是有定義的;
  • 作用域鍊:将JavaScript代碼的全局對象看做一個連結清單,當加載到全局變量時存放到連結清單的一個元素中,但加載到一個函數時将該函數加載到連結清單的一個元素中,在調用某一個變量時,從連結清單的第一個元素開始查找,如果遇到則使用,如果沒有則查找下一個,如果是函數則查找函數中的變量看是否存在;

繼續閱讀