作用域链本质上是一个指向变量对象的指针列表
关键词
- 执行环境
- 全局变量对象和活动对象
- 作用域链
函数的创建
函数在被创建时,会创建作用域链,它预先包含外层函数的活动对象,外层函数的外层函数的活动对象,...,全局变量对象。这样说比较抽象,事实上它预先包含为外层对象的作用域链,它被保存在函数内部的 [[Scope]] 属性中。
[[Scope]] 属性不能被开发者访问
用一个例子来说明:
function fnParent(){
//其它代码
...
const fnChild = function(){
//其它代码
...
}
}
在这个例子中,fnChild()被创建时, [[Scope]] 属性(作用域链)继承了fnParent()的作用域链。
函数的调用
函数调用时会创建函数的执行环境,然后将函数内部的 [[Scope]] 属性复制给函数执行环境作用域链。在此之后,会将 arguments对象 和函数调用时传递的实参初始化给函数的活动对象,并将函数的活动对象推入函数的执行环境作用域链的前端。
将上面的例子稍微加工:
function fnParent(){
//其它代码
...
x = 100
const fnChild = function(){
//其它代码
...
return x++
}
return fnChild
}
fnParent()() //101
在这个例子中,调用了fnParent()中的fnChild(),fnChild()的活动对象没有x,它将会沿着作用域链一层一层向后端搜索,直至找到fnParent()活动对象中的x。
下面这张图展示了上述函数中的作用域链的关系: