作用域链(Scope Chain)是由当前执行环境与上层执行环境的一系列变量对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。
如果你是第一次接触作用域链的概念,可能对上面这一句话的理解有一点困难。因此我们结合一个例子,以及对应的图示来说明。
var a = 20;
function test() {
var b = a + 10;
function innerTest() {
var c = 10;
return b + c;
}
return innerTest();
}
test();
在上面的例子中,全局,函数test,函数innerTest的执行上下文先后创建。我们假设他们的变量对象分别为VO(global),VO(test),VO(innerTest),那么innerTest的作用域链,则同时包含了这三个变量对象。
所以innerTest的执行上下文可如下表示。
innerTestEC = {
VO: {...}, // 变量对象
scopeChain: [VO(innerTest), VO(test), VO(global)], // 作用域链
this: {}
}
我们可以用一个数组来表示作用域链的有序性。数组第一项scopeChain[0]为作用域链的最前端,而数组的最后一项则为作用域链的最末端。所有作用域链的最末端都是全局变量对象。
很对人会用父子关系或者包含关系来理解当前作用域与上层作用域之间的关系。但我认为这样理解并不准确,以当前上下文的变量对象为起点,全局变量对象为终点的单方向通道我认为是更加贴切的理解。如图所示:
理解作用域链至关重要,但是更多的知识我们需要结合闭包来理解,因此更多的内容,在学习闭包的章节中扩展。