執行上下文就是評估和執行javascript代碼的環境的抽象概念.每當javascript運行的時候,它都是在執行上下文中運行javascript
是一種擁有後進先出數據結構的棧, 被用來儲存代碼運行時建立的全部執行上下文
爲了模擬執行上下文棧的行爲,讓咱們定義執行上下文棧是一個數組:java
ECStack = [];
當javascript引擎第一次遇到你的腳本時.它會建立一個全局的執行上下文,而且壓入當前執行棧,也就是數組ECStack中.數組
ECStack = [ globalContext ];
每當引擎遇到一個函數調用.它會爲該函數建立一個新的執行上下文而且壓入當前執行棧的頂部.數據結構
引擎會執行那些執行上下文位於棧頂的函數。當該函數執行結束時,執行上下文從棧中彈出,控制流程到達當前棧中的下一個上下文
如今javascript遇到下面的這段代碼:函數
function fun3() { console.log('fun3') } function fun2() { fun3(); } function fun1() { fun2(); } fun1();
// fun1() ECStack.push(<fun1> functionContext); // fun1中調用了fun2,還要建立fun2的上下文 ECStack.push(<fun2> functionContext); // fun2調用了fun3 ECStack.push(<fun3> functionContext); // fun3 執行完畢 ECStack.pop(); // fun2 執行完畢 ECStack.pop(); // fun1 執行完畢 ECStack.pop();
思考題:this
// 比較下面兩段代碼,試述兩段代碼的不一樣之處 var scope = "global scope"; function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f(); } checkscope(); // // B--------------------------- var scope = "global scope"; function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f; } checkscope()();
上面兩端代碼輸出值是同樣的, 都是local scope
可是執行上下文棧的變化不同
第一段代碼code
ECStack.push(<checkscope> functionContext) ECStack.push(<f> functionContext) ECStack.pop() ECStack.pop()
模擬第二段代碼ip
ECStack.push(<checkscope> functionContext) ECStack.pop() ECStack.push(<f> functionContext) ECStack.pop()
做用域是程序源代碼中定義變量的區域
做用域規定了若是查找變量,也就是肯定當前執行代碼對變量的訪問權限.
詞法做用域: javascript採用的是詞法做用域 也就是靜態做用域, 函數的做用域是在定義的時候就決定了
動態做用域: 函數的做用域是在函數調用的時候才決定的作用域
看下面例子io
var value = 1; function foo() { console.log(value); } function bar() { var value = 2; foo(); } bar();
假如javascript採用靜態做用域.
執行foo函數,先從foo函數內部查找是否有局部變量value.若是沒有,就根據書寫的位置,查找上面一層代碼. 也就是value等於1. 因此結果會打印1
假設javascript採用動態做用域.執行foo函數.依然是從foo函數內部查找是否有局部變量value.若是沒有.就從調用函數的做用域. 也就是bar函數內部查找value變量,因此打印2