JS靜態與動態作用域

JS靜態與動態作用域

JavaScript使用的是靜態作用域,非動態這件事要先提前知道

靜態作用域

  1. 懶人包 :

    會主動去尋找函數與變量定義時的狀況

  2. 例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    let a = '靜態作用域'

    function foo() {
    console.log(a);
    }
    function bar() {
    let a = '動態作用域'
    foo()
    }

    bar() // '靜態作用域'

    分析 :

    如果沒有作用域鏈的概念可以參考下面思維

    1
    2
    3
    4
    5
    6
    7
    8
    1. 前面都很正常的順順執行下來直到bar()
    2. 當執行bar時候,會從全局作用域(因為bar執行的地方在全局作用域)裡面尋找bar聲明的地方
    3. 進到bar函數作用域裡面(壓棧) // 所在第六行
    4. 在bar函數作用域裡面執行foo(),但在該函數作用域裡面沒有聲明foo,因此跑到上一層尋找,就是全局作用域
    5. 找到foo聲明的地方,並進入foo作用域裡面
    5. 試圖打印出a // 此時所在是第四行
    6. 因為foo作用域裡面沒有聲明變量a,因此又跑到全局作用域
    7. 找到a(靜態作用域)並打印出來

動態作用域

  1. 懶人包:

    會到執行時的環境尋找

  2. 例子(跟靜態相同):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    let a = '靜態作用域'

    function foo() {
    console.log(a);
    }
    function bar() {
    let a = '動態作用域'
    foo()
    }

    bar() // '動態作用域'

    分析:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    前面五點都一模一樣直到第六點
    1. 前面都很正常的順順執行下來直到bar()
    2. 當執行bar時候,會從全局作用域(因為bar執行的地方在全局作用域)裡面尋找bar聲明的地方
    3. 進到bar函數作用域裡面(壓棧) // 所在第六行
    4. 在bar函數作用域裡面執行foo(),但在該函數作用域裡面沒有聲明foo,因此跑到上一層尋找,就是全局作用域
    5. 找到foo聲明的地方,並進入foo作用域裡面
    5. 試圖打印出a

    6. 這時候找不到a並不會跑到上一層作用域鏈查找,而是回到執行時的環境也就是第八行所在的作用域查找
    7. 這時候就會發現a是動態作用域並打印出