变量对象

96 阅读2分钟

前言

对于每个执行上下文,都有三个重要属性:

  • 变量对象(Variable object,VO)
  • 作用域链(Scope chain)
  • this

今天重点讲讲创建变量对象的过程。

变量对象

变量对象(VO)有两种:全局对象和活动对象(AO)

全局对象

顾名思义,全局对象就是全局上下文中的对象,在客户端js中就是window对象。它在顶层代码中可以用this来引用,并访问全局对象中的各个属性和值。

活动对象

活动对象,就是函数上下文中的变量对象。

那么问题来了,你们知道它为什么叫作活动变量吗?

其实,变量对象只是一个概念上的描述,当创建上下文的时候才会被激活,成为活动对象,所以才叫activation object。

注意:活动对象是在创建上下文,也就是执行上下文之前的时候被创建,通过函数的arguments属性进行初始化。

包括三个部分:

  1. 函数的形参(全局上下文中除外)
  2. 上下文内部声明的函数(仅限于function声明的)
  3. 上下文内部声明的变量(仅限于用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
}