前面的话
前端日问 ,巩固基础,不打烊!!!
解答
作用域:指程序源代码中定义变量的区域。它规定了如何去查找变量。
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();
- 代码一: 先执行
注意:全局执行上下文这里没有写出,在代码开始时,就会被推入栈中,且是唯一的。
参考文章: