第12期 变量对象

147 阅读2分钟

当上下文控制权在某个执行上下文时,变量对象就会变成活动对象。

两者的区别是

1、变量对象(VO)是规范上或者是JS引擎上实现的,并不能在JS环境中直接访问。

2、当进入到一个执行上下文后,这个变量对象才会被激活,所以叫活动对象(AO),这时候活动对象上的各种属性才能被访问。

变量对象的创建

1、 Chrome 浏览器中,变量对象会首先获得函数的参数变量及其值;在 Firefox 浏览器中,是直接将参数对象 arguments 保存在变量对象中。

2、在变量对象中添加函数名为key 函数所在内存地址的引用为value,如果相同函数名则覆盖。

3、获取变量名为key,undefined为value,遇到同名的函数名或者同名的变量名则跳过,不进行覆盖。此处为var声明的变量,let和const声明是执行阶段才开始执行。

全局上下文的变量对象

windowEC = {
    VO:window
}

变量对象 相关例子1

var a = 20; 
var b = 30;
function fn() {console.log('fn')} ; 
function fn() {console.log('cover fn.')};
function a() {console.log('cover a.')}; 
console.log(a); 
console.log(b);
fn(); 
var fn = 'I wa cover function named fn.'; 
console.log (fn); 

创建阶段

函数优先
    fn
    fn(覆盖上一个fn)
    a
    变量
    a(跳过)
    b
    fn(跳过)

VO = {
    arguments:{},
    fn:<fn reference>,
    a:<a reference>,
    b:undefined
}

执行阶段

AO = {
    arguments:{},
    fn:'I wa cover function named fn.',
    a:20,
    b:30
}

输出的值是:

20

30

cover fn.

I wa cover function named fn.

变量对象 相关例子2

函数 bar 的变量对象中是否包含了变量a?

function foo () { 
    var a = 20; 

    function bar() { 
    a = 30; // 我猜没有 这里改的应该是foo的变量对象里面的a变量
    console.log(a); 
    } 
    bar() ; 
    console.log(a);// 这里a也被改变了
} 
foo();

30
30

变量对象 相关例子3

函数执行上下文带参数的话,在创建阶段就会被赋值。

function foo(a) {
  var b = 2;
  function c() {}
  var d = function() {};

  b = 3;
}

foo(1);


AO(foo) = {
    arguments: {
        0: 1,
        length: 1
    },
    a: 1,
    b: undefined,
    c: <c reference>,
    d: undefined
}

变量提升

console.log(a);
var a = 30;

相当于

var a = undefined;
console.log(a);
a = 30;

通过var定义的变量,会在变量对象创建阶段给变量a赋值undefined,在console.log(a)的时候就不会报错,我们叫做变量提升。

函数提升

foo();
function foo() {
    console.log('foo');
}

相当于

function foo() {
    console.log('foo');
}
foo();

在变量对象创建的时候,foo已经指向,不像变量会被赋值undefined,在执行foo()的时候就不会报错,也能够正常的输出'foo',我们叫做函数提升。