1. 程式人生 > >詞法作用域

詞法作用域

... 比較 定義 聲明 如果 define 原型 nbsp java

作用域

域表示的就是 範圍, 即 作用範圍. 就是一個名字在什麽地方可以被使用, 什麽時候不能使用.

塊級作用域

即塊級別的作用範圍

    // 在 C , Java 等編程語言中, 下面的語法報錯
    {
        var num = 123;  // int 
        {
            console.log( num ); // => 123
        }
    }
    console.log( num ); // 報錯

在 js 中采用詞法作用域

所謂的 詞法( 代碼 )作用域, 就是代碼在編寫過程中體現出來的作用範圍. 代碼一旦寫好, 不用執行,
作用範圍就已經確定好了. 這個就是所謂詞法作用域.

在 js 中詞法作用域規則:

  1. 函數允許訪問函數外的數據.
  2. 整個代碼結構中只有函數可以限定作用域.
  3. 作用規則首先使用提升規則分析
  4. 如果當前作用規則中有名字了, 就不考慮外面的名字

作用域鏈

可以發現只有函數可以制造作用域結構. 那麽只要是代碼, 至少有一個作用域, 即全局作用域.
凡是代碼中有函數, 那麽這個函數就構成另一個作用域. 如果函數中還有函數, 那麽再這個作用域中就
又可以誕生一個作用域. 那麽將這樣的所有的作用域列出來, 可以有一個結構: 函數內指向函數外的鏈式結構.

繪制作用域鏈的步驟:

  1. 看整個全局是一條鏈, 即頂級鏈, 記為 0 級鏈
  2. 看全局作用域中, 有什麽成員聲明, 就以方格的形式繪制到 0 級練上
  3. 再找函數, 只有函數可以限制作用域, 因此從函數中引入新鏈, 標記為 1 級鏈
  4. 然後在每一個 1 級鏈中再次往復剛才的行為

變量的訪問規則

  1. 首先看變量在第幾條鏈上, 在該鏈上看是否有變量的定義與賦值, 如果有直接使用
  2. 如果沒有到上一級鏈上找( n - 1 級鏈 ), 如果有直接用, 停止繼續查找.
  3. 如果還沒有再次往上剛找... 直到全局鏈( 0 級 ), 還沒有就是 is not defined
  4. 註意, 切記 同級的鏈不可混合查找

如何分析代碼

    1. 在分析代碼的時候切記從代碼的運行進度上來分析, 如果代碼給變量賦值了, 一定要標記到圖中
    2. 如果代碼比較復雜, 可以在圖中描述代碼的內容, 有事甚至需要將原型圖與作用域圖合並分析
    var num = 123;
    function f1() {
        console.log( num );
    }
    function f2() {
        var num = 456;
        f1();
    }
    f2();

補充

  1. 聲明變量使用 var, 如果不使用 var 聲明的變量就是全局變量( 禁用 )
  2. 因為在任何代碼結構中都可以使用該語法. 那麽在代碼維護的時候會有問題. 所以除非特殊原因不要這麽用.
  3. 下面的代碼的錯誤

function foo () {
    var i1 = 1  // 局部
        i2 = 2, // 全局
        i3 = 3; // 全局

}

   4.此時註意

var arr = [];
for ( var i = 0; i < 10; i++ ) {
    arr.push( i );
}
for ( var i = 0; i < 10; i++ ) {
    console.log( arr[ i ] );
}
// 一般都是將變量的聲明全部放到開始的位置, 避免出現因為提升而造成的錯誤
var arr = [], 
    i = 0;
for ( i=0; i < 10; i++ ) {
    arr.push( i );
}
for ( i = 0; i < 10; i++ ) {
    console.log( arr[ i ] );
}

詞法作用域