JavaScript之变量对象

概述

JavaScript 的可执行代码,具备执行上下文,而每一个上下文包括如下 3 个属性:javascript

  1. 变量对象(variable object, 简称 VO)
  2. 做用域链(scope chain)
  3. this

变量对象提供了当前环境所需的变量和函数
做用域链用于保证 JS 中变量和函数有序地访问
this 为函数提供了执行者对象java

一个上下文的执行周期能够用下图示意:
express

本文就来介绍执行上下文中的变量对象数组

那什么是变量对象呢?先看定义:浏览器

变量对象是与执行上下文相关的数据做用域,用于存储执行上下文中的变量和函数声明。bash

不一样的执行上下文,变量对象会有一些差异。接下来就分别针对不一样的上下文讨论其区别。闭包

1、全局上下文

全局对象(Global object) 是在进入任何执行上下文以前就已经建立了的对象; 这个对象只存在一份,它的属性在程序中任何地方均可以访问,全局对象的生命周期终止于程序退出那一刻。app

在全局代码的上下文执行环境中,变量对象就是全局对象,在浏览器中,就是 window 对象。函数

此时,咱们能够用 this 和 self 来访问到全局对象,也就是它自己post

console.log(this)  // window
console.log(self)  // window
复制代码

其次,全局对象初始建立阶段将 Math、String、Date、parseInt 等函数做为自身方法,还会把全局变量做为本身的属性。

用伪代码表示就是:

global = {
    Math: <...> Date: <...> window: global // 引用自身 } 复制代码

2、函数上下文

咱们已经知道,变量对象存储量执行上下文中的函数声明和变量,在函数上下文中,多了arguments(函数参数列表), 一个类数组对象。

用伪代码来表示:

VO = {
    arguments: Arguments,
    variables: undefine,
    functionName: <Function reference>
}
复制代码

函数未进入执行阶段以前,变量对象中的属性都不能访问!可是进入执行阶段以后,变量对象转变为了活动对象(activation object)。

因此,在函数上下文中,咱们将活动对象(activation object)做为变量对象,活动对象最开始只包含一个变量就是 arguments 对象(这个对象是全局环境中没有的)。

arguments 的属性值 Arguments 它包括以下属性:

  • callee — 谁调用了本函数
  • length — 真正传递的参数个数
  • properties-indexes (字符串类型的整数) 属性的值就是函数的参数值(按参数列表从左到右排列)

3、建立过程

咱们再一次来看这个过程图:

建立阶段

全局对象初始化的时候,就将变量对象引用了自身。 而函数的建立却有须要注意的地方。

函数在建立阶段就建立了变量对象
其中,变量对象包括:

  1. 当前函数的参数列表,创建 Arguments 对象。
  2. 全部的函数声明(不包括函数表达式哦!),直接指向函数
  3. 全部的变量声明(var 声明的变量),默认为 undefined

进入执行上下文时,函数声明和变量声明都会提早,这就是声明提高,可是变量声明的值都是undefined,而函数声明的变量已经能够指向函数。变量声明的优先级最低。

看下面这段代码:

function foo(a, b) {
  var c = 10;
  function d() {}
  var e = function _e() {};
  (function x() {});
}
  
foo(10); 
复制代码

当进入函数 foo 时,其变量对象的表现形式为:

VO = {
    arguments: {
        0: 10,
        1: undefined,
        length: 1
    }
    c: undefined,
    d: <function reference to d>, e: undefined, } 复制代码

x 是函数表达式,因此不在变量对象当中,e 变量引用的值也是函数表达式,因此变量 e 自己是声明,因此在变量对象当中。

执行阶段

当前进入执行阶段,变量对象激活成活动对象,函数会顺序执行代码,改变变量对象的值:
以上代码就变成:

AO = {
    arguments: {
        0: 10,
        1: undefined,
        length: 1
    }
    c: 10,
    d: <reference to function declaration d>,
    e: <reference to Function expression to _e>,
}
复制代码

接下来看一段代码:

console.log(foo);

function foo() {
    console.log("123")
}

var foo = "456";
复制代码

以上会打印函数,是由于:

变量优先处理函数声明,再是变量声明。

再看一段代码:

if (true) {
  var a = 1;
} else {
  var b = 2;
}
console.log(a);  // 1
console.log(b);  // undefined
复制代码

虽然 else 中的代码永远不会被执行,可是 b 的变量声明在执行以前就默认被设置成 undefined了。

总结

执行上下文包括三个属性,变量对象,做用域链,this, 不一样的执行上下文,变量对象是有区别的。

全局上下文中,变量对象就是自己。

函数上下文中,变量对象包括:arguments, 函数声明,变量声明。在函数建立阶段,变量对象有默认值,进入执行阶段后,变量对象会被激活成活动对象,而后变量对象的值被顺序改变。

欢迎关注个人我的公众号“谢南波”,专一分享原创文章。

掘金专栏 JavaScript 系列文章

  1. JavaScript之变量及做用域
  2. JavaScript之声明提高
  3. JavaScript之执行上下文
  4. JavaScript之变量对象
  5. JavaScript原型与原型链
  6. JavaScript之做用域链
  7. JavaScript之闭包
  8. JavaScript之this
  9. JavaScript之arguments
  10. JavaScript之按值传递
  11. JavaScript之例题中完全理解this
  12. JavaScript专题之模拟实现call和apply
相关文章
相关标签/搜索