前言
对于每个执行上下文,都有三个重要属性:
- 变量对象(Variable object,VO)
- 作用域链(Scope chain)
- this
今天重点讲讲创建变量对象的过程。
变量对象
变量对象(VO)有两种:全局对象和活动对象(AO)
全局对象
顾名思义,全局对象就是全局上下文中的对象,在客户端js中就是window对象。它在顶层代码中可以用this来引用,并访问全局对象中的各个属性和值。
活动对象
活动对象,就是函数上下文中的变量对象。
那么问题来了,你们知道它为什么叫作活动变量吗?
其实,变量对象只是一个概念上的描述,当创建上下文的时候才会被激活,成为活动对象,所以才叫activation object。
注意:活动对象是在创建上下文,也就是执行上下文之前的时候被创建,通过函数的arguments属性进行初始化。
包括三个部分:
- 函数的形参(全局上下文中除外)
- 上下文内部声明的函数(仅限于function声明的)
- 上下文内部声明的变量(仅限于用var声明的)
从变量对象的角度看代码执行过程
变量对象创建过程
1.将参数对象arguments存放在变量对象中
2.寻找用function声明的函数,然后将函数的内存地址存放到变量对象中
3.寻找用var声明的变量,然后存放到变量对象
注意
:重名的函数以后者
为准,重名的变量以前者
为准
举个例子:
function foo(a) {
var b = 2;
function c() {}
var d = function() {};
b = 3;
}
foo(1);
在进入执行上下文后,这时候的 AO 是:
AO = {
arguments: {
0: 1,
length: 1
},
a: 1,
b: undefined,
c: reference to function c(){},
d: undefined
}
变量对象执行过程
还是上面的例子
AO = {
arguments: {
0: 1,
length: 1
},
a: 1,
b: 2,
c: reference to function c(){},
d: undefined
}
思考题
来个例子巩固一下上面所说的:
function test() {
console.log(a);
console.log(foo());
var a = 1;
function foo() {
return 2;
}}
test();
当运行test函数,对应的上下文创建,可以采用如下形式来表达整个过程
// 创建阶段
testEC={
VO:{}, // 变量对象
scopeChain:[], // 作用域链
this:{}
}
VO={
arguments:{...},
foo:<foo reference>,
a:undefined
}