当JavaScript代码执行一段可执行代码(executable code)时,会创建对应的执行上下文(execution context)。
对于每个执行上下文都会有三个重要的属性:
变量属性(Variable object,VO)
作用域链(scope chain)
this
作用域链
在《JavaScript深入之变量对象》中讲到,当我们查找一个变量的时候,会在当前额上下文的变量中查找,如果没有找到就从父级的执行上下文的变量中去查找,一直到全局的执行上下文也就是全局对象。这样多个执行上下文变量对象构成的链表就叫做作用域链
函数作用域
函数的作用域在函数定义的时候就决定了。
举个栗子:
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();
我们都知道,上端代码执行上下文栈的进出过程是这样的:
ECStack.push(<checkscope> functionContext);
ECStack.pop();
ECStack.push(<f> functionContext);
ECStack.pop();
那么有些小伙伴就会有疑惑了,为什么checkscope执行上下文已经从执行上下文栈中弹出来,为什么f函数还能够访问到它作用域下的属性。这里就要知道:函数的作用域在函数定义的时候就决定了
函数创建时,各自的**[[scope]]**为:
checkscope.[[scope]] = [
globalContext.VO
];
f.[[scope]] = [
fContext.AO,
globalContext.VO
];
所以f函数在checkscope的执行上下文从执行上下文栈中弹出的时候依然会访问的到它的属性