变量对象(Variable Object)

16 阅读2分钟
1 一个执行上下文的生命周期可以分为两个阶段:
  • 创建阶段
    • 执行上下文会分别 创建变量对象,建立作用域链,以及确定 this 指向。
  • 代码执行阶段
    • 创建完成之后,就会开始执行代码,会完成变量赋值,函数引用,以及执行其他代码。

创建(生成变量对象、建立作用域链、确定this指向) -------》 执行(变量赋值、函数引用、执行其他代码) -------执行完毕后出栈,等待被回收-------》

2 变量对象的创建,依次经历了以下几个过程:
  1. 建立 arguments 对象:检查当前上下文中的参数,建立该对象下的 属性 与 属性值。(函数参数)
  2. 检查当前上下文的函数声明,也就是使用 function 关键字声明的函数。在变量对象中以函数名建立一个属性,属性值为指向该函数所在内存地址的引用。
  3. 检查当前上下文中的变量声明,每找到一个变量声明,就在变量对象中以变量名建立一个属性,属性值为 undefined。

如果变量与函数同名,则在这个阶段,以函数值为准。

变量对象创建过程:

创建 arguments 对象 -------》 检查 function 函数声明创建属性 -------》 检查 var 变量声明创建属性

function 声明会比 var 声明优先级更高一点

执行上下文未进入执行阶段之前,变量对象中的属性都不能访问!但是进入执行阶段之后,变量对象转变为了活动对象,里面的属性都能被访问了,然后开始进行执行阶段的操作。

3 全局上下文的变量对象

以浏览器中为例,全局对象为 window。 全局上下文有一个特殊的地方,它的变量对象,就是 window 对象。而这个特殊,在 this 指向上也同样适用,this 也是指向 window。

// 以浏览器中为例,全局对象为window
// 全局上下文
windowEC = {
  VO: Window,
  scopeChain: {},
  this: Window
} 

全局上下文的生命周期,与程序的生命周期一致,只要程序运行不结束,比如关掉浏览器窗口,全局上下文就会一直存在。其他所有的上下文环境,都能直接访问全局上下文的属性。

4 let/const

let/const 声明的变量,仍然会提前被收集到变量对象中,但和 var 不同的是,let/const 定义的变量,不会在这个时候给他赋值undefined。

因为完全没有赋值,即使变量提升了,我们也不能在赋值之前调用他。这就是我们常说的暂时性死区。