JS进阶系列-第五篇-变量对象

Posted by Kylen on 2019-07-18

前言

我们知道一个函数执行时,会创建一个执行上下文,而一个执行上下文的声明周期可以分为两个阶段:

  • 创建阶段
    在创建阶段,执行上下文会创建变量对象、生成作用域链、确定this的指向
  • 代码执行阶段
    创建完成之后,会执行代码,包括赋值语句、函数调用和其他语句

js-advanced 2019-07-17 下午5.56.59.png

从这里我们就可以看出详细了解执行上下文极为重要,因为其中涉及到了变量对象,作用域链,this等很多人没有怎么弄明白,但是却极为重要的概念,它关系到我们能不能真正理解JavaScript。在后面的文章中我们会一一详细总结,这里我们先重点了解变量对象。

变量对象(Variable Object)

变量对象的生成规则如下:

  1. 根据形参建立当前上下文的参数,如果是函数则是函数所有的形参;没有实参,属性值默认为undefined
  2. 当前执行上下文中的函数声明,在变量对象中以key-value的形式存在;如果变量对象上已存在相同名称的属性,则覆盖
  3. 当前执行上下文中的变量声明,由名称和对应值(undefined)组成一个变量对象的属性创建,若已存在相同名称的属性,则忽略,防止覆盖上面两步生成的属性。

使用let const定义的变量会产生暂时性死区,即不允许变量定义之前使用变量。

根据这个规则,理解变量提升就变得十分简单了。

举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
// demo01
function test() {
console.log(a);
console.log(foo());

var a = 1;
function foo() {
return 2;
}
}

test();

当执行到test()时,函数test的执行上下文开始创建,以如下形式来表示:

1
2
3
4
5
6
7
8
9
10
// 创建阶段
testEc = {
VO: {}, // 变量对象
}

VO = {
arguments: {...}, // 用来表示函数的参数,并不代表真实情况
foo: <foo reference>, // 表示foo地址的引用
a: undefined
}

进入执行阶段,变量对象变成活动对象(activation object)。变量对象和活动对象是同一个对象,只是处于执行上下文不同的生命周期,只有位于执行栈顶部的执行上下文中的变量对
象才会变成活动对象。

1
2
3
4
5
6
7
8
// 执行阶段
VO -> AO

AO = {
arguments: {...},
foo: <foo reference>,
a: 1
}

参考链接

三、变量对象
【进阶1-2期】JavaScript深入之执行上下文栈和变量对象