前面的話
前端日問 ,鞏固基礎,不打烊!!!
解答
作用域:指程序源代碼中定義變量的區域。它規定了如何去查找變量。
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();
- 代碼一: 先執行
注意:全局執行上下文這裏沒有寫出,在代碼開始時,就會被推入棧中,且是唯一的。
參考文章: