概念
作用域(scope)
每个JavaScript函数都是一个对象,对象中的属性都是可以访问的,但是有些却不能访问,而这些属性仅供JavaScript引擎存取,[[scope]]就是其中一个。[[scope]]就是我们所说的作用域,其中存储了执行期上下文集合。
在学习过程中会涉及到两个对象名称AO、GO
作用域链(Scope chain)
[[scope]]中所存储的执行期上下文对象集合,这个集合呈链式链接,我们把这个链式叫做作用域链。
AO(Active Object)私有变量对象
在【函数执行上下文EC中】,因为【私有变量对象 AO】 是要保存当前私有上下文中所有的变量,而一个函数内的变量包括:形参变量、局部变量、自身函数对象引用变量、arguments、this。 为了保存这些变量,所以特意创建了一个对象,称它为【活动对象(私有变量对象)AO(xx)】,函数内所需的变量就都保存在 【私有变量对象AO(xx)】 中,所以在函数执行上下文中,变量对象 VO 的具体表现也就是【私有变量对象AO(xx)】。
GO(Global Object)全局对象
预定义的对象,【浏览器把所有后期需要供JS调取使用的属性和方法(内置),都放置在了GO当中。并且在全局当中创建一个叫做window的变量指向它。】通过使用全局对象,可以访问所有其他所有预定义的对象、函数和属性。
例如:
function test(){
var a= 10;
function b(){
var c=1
}
b()
}
var g = 100
test();
- test函数被声明,创建test.[[scope]], test.[[scope]] ==> 0 : GO
- test函数被执行时,就会产AO,同时将test.[[scope]]
在执行上面代码的时候,首先会进行全局初始化,会执行以下操作
- 初始化环境执行栈
- test函数被声明,创建test.[[scope]]
// Scope chain
test.[[scope]] = [
// GO
{
this:window
window:(Object),
document:(Object)
test:(function),
g:100,
}
]
-
当执行test函数的时候,首先会创建环境变量对象,也就是test函数的AO对象,然后初始化作用域链等
// Scope chain test.[[scope]] = [ // AO { this:window, a:10, b:(function) }, // GO { this:window window:(Object), document:(Object) test:(function), g:100, } ]
-
当执行b函数的时候,b函数也会产生自己的AO对象,但是b的[[scope]]对象中,则会包含test和函数的[[scope]]对象
// Scope chain b.[[scope]] = [ // AO { this:window, c:1 }, // test 函数AO { this:window, a:10, b:(function) }, // GO { this:window window:(Object), document:(Object) test:(function), g:100, } ]
**在函数中查找变量,从其作用域链的顶端依次向下查找,从Scope chain 的0位依次查到最后一位。**