如果不明白VO/AO可以先看一看上一个博客内容:理解javascript执行环境(执行上下文)
正文内容
作用域
- 一块代码可执行区域,在该区域中的变量和函数在区域外部是不可见的
作用域链
- 由多个执行上下文的变量对象构成的链表就叫做作用域链。
- 当一个函数被创建时会默认添加一个名为[[Scope]]的特殊内部属性,如果该函数时一个全局函数,那么在该函数被创建时会预先创建一个包含全局变量对象(全局VO)的作用域链,这个作用域链被保存在该函数的[[Scope]]属性中,当该函数调用时,会为该函数创建一个执行环境,通过复制[[Scope]]属性中的对象构建起执行环境作用域链,之后又为该函数创建一个活动对象(AO)并推入执行环境作用域链的前端。如果该执行环境内部还有子函数,那么将执行环境作用域链保存到子函数的[[Scope]]属性中,以便子函数调用时取用
作用域链的创建
第一步 当程序执行时创建全局作用域和全局VO对象,发现fn1与fn2函数是在全局环境下定义,那么在创建fn1与fn2函数时预先创建一个包含全局VO对象指针的作用域链,保存到这两个函数各自的[[Scope]]属性当中,
<script>
// 全局环境创建 / 创建 VO 对象
var a = 7
// fn1定义在全局环境下 ,创建包含全局VO指针的作用域链Scope Chain,保存到fn1.[[Scope]]属性中
function fn1 () {
var b = 8
function child () {
var c = a + b
}
child()
}
// fn2也定义在全局环境下 ,创建包含全局VO指针的作用域链Scope Chain,保存到fn2.[[Scope]]属性中
function fn2 () {
var x = a
}
fn1()
fn2()
</script>
第二步,当程序执行到fn1()调用,程序执行流进入fn1函数体中,创建fn1执行环境,并创建fn1的AO对象,之后将AO对象的指针添加到fn1.[[Scope]]中作用域链的前端
<script>
// 全局环境创建 / 创建 VO 对象
var a = 7
function fn1 () {
// 创建fn1执行环境 / 创建AO对象,将AO对象的指针添加到fn1.[[Scope]]中作用域链的最前端
var b = 8
function child () {
var c = a + b
}
child()
}
function fn2 () {
var x = a
}
fn1()
fn2()
</script>
第三步,程序在fn1中继续执行,发现函数child是定义在fn1的执行环境中的,那么将fn1.[[Scope]]中保存的作用域链复制给child.[[Scope]],这时fn1.[[Scope]]中保存的作用域链应该是Scope -> fn1 AO -> Global VO
<script>
// 全局环境创建 / 创建 VO 对象
var a = 7
function fn1 () {
// 创建fn1执行环境 / 创建AO对象,将AO对象的指针添加到fn1.[[Scope]]中作用域链的最前端
var b = 8
// 发现child定义在fn1执行环境中,将fn1.[[Scope]]中保存的作用域链复制给child.[[Scope]]
function child () {
var c = a + b
}
child()
}
function fn2 () {
var x = a
}
fn1()
fn2()
</script>
第四步,发现child()函数调用,程序进入child函数中,创建环境与AO对象,并将AO对象添加到child.[[Scope]]中作用域链的前端
第五步,程序退出child函数并将其销毁,退出fn1函数并将其销毁,发现fn2()函数调用,进入fn2函数体内部,进行与fn1类似的操作
作用域链的访问
拿child函数来举例
1. 程序进入child函数体内部,查询child环境下的AO对象,没有发现a或b变量
2. 向后查找作用域链,发现fn1环境下的AO对象有变量b,但是没有变量a
3. 继续沿着作用域链向后查找,发现全局环境下的VO对象中包含着变量a
4. 取得a和b的值进行加法操作并将结果赋值给c
5. 全局VO永远处于作用域链的最末端,如果在全局VO中仍然没有找到需要的数据,那么浏览器将会报错
6. 作用域链 -> child AO -> fn1 AO -> Global VO
参考资料
- JavaScript高级程序设计(第3版)第七章-179页
本文详细解释了JavaScript中作用域和作用域链的概念,包括作用域的定义、作用域链的创建过程及其如何帮助函数访问不同层级的变量。

被折叠的 条评论
为什么被折叠?



