一介绍
我们都知道变量对象会保存执行上下文中的一些数据,例如function declarations、formal parameters、variable、arguments,这些数据都会成为变量对象的属性。
当一进入执行上下文的时候,变量对象会进行初始化,在代码执行的阶段变量对象中的一些数据也会进行更新。
同样与执行上下文密切相关还有作用域链,本篇文章将会介绍执行上下文中的作用域链。
二定义
作用域链与执行上下文密切相关,一系列变量对象组成的链常用于在标识符解析时查找变量。
让我们先来举一个简单的例子:
var x = 10;
function Foo() {
var y = 20;
function bar() {
console.log(x + y);
}
return bar;
}
Foo()(); //30
我们都知道没进入一个执行上下文,就会有一个与该上下文密切相关的变量对象。对于全局上下文(global context)来说,其变量对象(variable object)就是全局对象(global object)。对于函数上下文来说就是活动对象(activation object),也称为变量对象。
对于内部上下文来说,其作用域链(Scope Chain)是由所有父级的变量对象和自身的变量对象组成的。这条链常用于变量的查找。在上面这个例子中函数bar上下文的作用域链包括bar的活动对象、Foo的变量对象、全局变量对象。
当函数调用时,该函数上下文中的作用域链就会被创建。并且是由该函数上下文中的活动对象和函数的内部属性[[scope]]所组成的。 就像下面这样:
activeExecutionContext = {
VO: {...}, // or AO
this: thisValue,
Scope: [ // Scope chain
// list of all variable objects
// for identifiers lookup
]
};
其作用域就是下面这样:
Scope = AO + [[scope]]
常常将作用域链放在一个栈中,例如用js中的数组来模拟栈可以表示成下面这个样子:
var Scope = [vo1,vo2,vo3,...] //scope chain
当然你也可以用对象来表示,通过引用父级作用域表示成分层对象链,用__parent__属性来指向外部上下文中的变量对象。 例如:
var VO1 = {__parent__: VO2, ... other data}; -->
var VO2 = {__parent__: VO3, ... other data}; -->
// etc.
以上这种Scope = AO + [[scope]]的标识符解析过程,与函数的生命周期有关。将会在下面继续讨论