JavaScript 之变量对象

首发地址: https://github.com/jeuino/Blo...

前言

在上一篇《JavaScript 以内存空间》中,简单介绍了下 JavaScript 中的变量是如何存储的。本篇文章将总结一下变量和函数在运行时是如何查找并引用的。git

变量对象

Image  11

《JavaScript 之执行上下文》中,咱们知道了一段代码在开始执行时,首先会建立一个执行上下文。而当进入执行上下文时,就会建立一个变量对象,此时代码还未执行。github

变量对象是与执行上下文相关的数据做用域,执行上下文中定义的全部变量和函数都保存在这个对象中。能够将变量对象理解为做用域这个抽象概念的实体,当代码执行时,是从变量对象中查找是否存在相应的变量的。它具体是如何查找的呢?咱们继续往下看。函数

变量对象的建立,依次经历了如下三个过程:ui

  • 扫描当前执行上下文中的全部形参(针对函数执行上下文):该过程生成 Arguments 对象,并建立以形参变量名做为属性名,形参变量值做为属性值的变量对象属性;咱们都知道,在函数中,有一个 arguments 对象,存储了全部传递给函数的参数,那么这个对象是哪里来的呢,其实它就是在这个阶段生成的。
  • 扫描当前执行上下文中的全部函数声明:该过程建立以函数名做为属性名,函数的引用地址做为属性值的变量对象属性;
  • 扫描当前执行上下文中的全部变量声明:该过程建立以变量名做为属性名,undefined 做为属性值的变量对象属性;(变量的赋值是在代码执行阶段进行的)

变量对象的建立,是优先扫描函数声明的,若是变量与函数同名,则以函数为主。下面简单解释下缘由:
假设变量对象(做用域)中已经存在一个名为 foo 的属性,它表明一个函数引用。当扫描变量声明时,又遇到一个命名为 foo 的变量,解释器会询问变量对象(做用域)是否已经存在一个该名称的标识符,若是存在,解释器会忽略该指令,继续执行;不然它会要求变量对象声明一个命名为 foo 的属性,并赋值为 undefined。
Image  12this

因为全局执行上下文和函数执行上下文中的变量对象有一些差别,因此下面对它们分别进行介绍。spa

全局执行上下文

在全局执行上下文中,变量对象初始化是全局对象,也就是 window 对象。所以全部声明的全局变量和函数都是做为 window 对象的属性和方法建立的。3d

什么是全局对象

全局对象是预约义的对象,做为 JavaScript 的全局函数和全局属性的占位符。经过使用全局对象,能够访问其余全部预约义的对象、函数和属性。

全局对象不是任何对象的属性,因此它没有名称。code

在顶层 JavaScript 代码中,能够用关键字 this 引用全局对象。对象

由于全局对象是做用域链的头,这意味着在顶层 JavaScript 代码中声明的全部变量都将成为全局对象的属性。blog

函数执行上下文

在函数执行上下文中,变量对象就是其活动对象(activation object, AO)

什么是活动对象?

变量对象和活动对象实际上是一个对象,二者意思相同,只是处于执行上下文的不一样生命周期。

执行上下文的生命周期包括两个阶段:建立阶段和执行阶段。后续会写一篇文章单独总结。

变量对象就是在建立阶段时初始化的,此时代码还未执行,变量对象中的属性不能被访问。进入执行阶段后,开始逐行执行代码,此时变量对象就会被激活变成活动对象(AO),其各类属性才能被访问。此时就能够经过查找变量对象上是否存在某属性的方式查找声明的变量和函数,获取到引用后进行变量赋值、函数调用等操做。


咱们一块儿来看下下面这段代码生成的变量对象是什么样子的:

function fn(a, b) {
    var c = 2;
    function fn1() {}
    var d = function () {};
}

fn(1, 2, 3);
// fn 执行上下文中的变量对象
VO = {
    Arguments: {
        0: 1,
        1: 2,
        2: 3,
        length: 3
    },
    a: 1,
    b: 2,
    c: undefined,
    fn1: <fn1 reference>,
    d: undefined
}

Image  13

此时的变量对象是在代码执行前建立的,变量对象中的属性都不能访问。在进入执行阶段以后,变量对象变成了活动对象,此时变量对象的属性能够被访问了。而后开始执行代码,代码执行的过程当中可能会修改变量对象的属性值。

仍是上面的例子,当代码执行完毕,这时的 AO 变成:

AO = {
    Arguments: {
        0: 1,
        1: 2,
        2: 3,
        length: 3
    },
    a: 1,
    b: 2,
    c: 2,
    fn1: <fn1 reference>,
    d: <FunctionExpression "d" reference>
}

总结:

  • 执行上下文中声明的全部变量和函数都保存在变量对象中;
  • 变量对象能够理解为做用域这个抽象概念的实体;
  • 变量对象在代码执行前就已经初始化好了,这很好的解释了变量和函数的提高问题;
  • 进入代码执行阶段,访问声明的变量和函数时,就会从当前执行上下文的变量对象中查找。

下一篇

在每一个执行上下文中,都包括三个重要的属性:

  • 变量对象(Variable Object,VO)
  • 做用域链(Scope Chain)
  • this指向

下篇文章将开始介绍执行上下文中的this关键字,敬请期待。

参考:

JavaScript深刻之变量对象
JavaScript 之深刻理解执行上下文
相关文章
相关标签/搜索