4 / 5 詞法作用域和動態作用域

前面的話

前端日問 ,鞏固基礎,不打烊!!!

解答

作用域:指程序源代碼中定義變量的區域它規定了如何去查找變量

JavaScript中採用的是詞法作用域,也就是靜態作用域。因爲JavaScript採用的是詞法作用域,所以函數的作用域在函數定義的時候就決定了。

var value = 1;

function foo() {
    console.log(value);
}

function bar() {
    var value = 2;
    foo();
}

bar(); // ? 

上面的結果爲:1

  • 原因: 執行foo函數是,先看foo函數內部是否有局部變量value, 如果沒有就根據其定義的位置,查找上層的代碼,value爲1.
  • 如果採用動態作用域,先出foo函數內部查看是否有局部的變量value,如果沒有,就從調用它的函數bar的中找,結果爲2。(bash採用的是動態作用域)

題目

// 代碼一:
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope();
// 代碼二:
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;
}
checkscope()();
  • 兩份代碼都是:local scope,因爲函數f是在checkscope函數中定義的,所以查找變量scope時,先在函數f內部找,沒有的話,就到其定義的位置中去查找,即checkscope內部查找,爲local scope
  • 兩份代碼的區別是啥呢? 是執行上下文棧 的不同:
    • 代碼一: 先執行checkscope函數:ECStack.push(<checkscope> functionContext);;而checkscope函數裏面又執行了f函數:ECStack.push(<f> functionContext);;執行完畢後,f的執行上下文出棧:ECStack.pop(); ; 接着checkscope的執行上下文出棧:ECStack.pop();
    • 代碼二:先執行checkscope函數:ECStack.push(<checkscope> functionContext);;執行完畢後,出棧:ECStack.pop();; 接着執行f函數:ECStack.push(<f> functionContext);; 執行完畢後,出棧:ECStack.pop();

注意:全局執行上下文這裏沒有寫出,在代碼開始時,就會被推入棧中,且是唯一的。

參考文章:

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