JavaScript基础教程 15分钟了解变量对象
沉沙 2018-06-19 来源 : 阅读 1399 评论 0

摘要:变量对象是与执行上下文相关的数据作用域,存储了在上下文中定义的变量和函数声明。希望阅读本篇文章以后大家有所收获,帮助大家对JavaScript的理解更加深入。

前言

当JavaScript代码执行一段可执行代码(executable code)时,会创建对应的执行上下文(execution context)。

对于每个执行上下文,都有三个重要属性:

· 变量对象(Variable object,VO)

· 作用域链(Scope chain)

· this

今天重点讲讲创建变量对象的过程。

变量对象是与执行上下文相关的数据作用域,存储了在上下文中定义的变量和函数声明。

因为不同执行上下文下的变量对象稍有不同,所以我们来聊聊全局上下文下的变量对象和函数上下文下的变量对象。

全局上下文

我们先了解一个概念,叫全局对象。在W3C school中也有介绍:

全局对象是预定义的对象,作为 JavaScript 的全局函数和全局属性的占位符。通过使用全局对象,可以访问所有其他所有预定义的对象、函数和属性。

在顶层 JavaScript 代码中,可以用关键字 this 引用全局对象。因为全局对象是作用域链的头,这意味着所有非限定性的变量和函数名都会作为该对象的属性来查询。

例如,当JavaScript 代码引用 parseInt() 函数时,它引用的是全局对象的 parseInt 属性。全局对象是作用域链的头,还意味着在顶层 JavaScript 代码中声明的所有变量都将成为全局对象的属性。

如果看的不是很懂的话,容我再来介绍下全局对象:

1.可以通过this引用,在客户端JavaScript中,全局对象就是Window对象。

console.log(this);

   

2.全局对象是由Object构造函数实例化的一个对象。

console.log(this instanceof Object);

   

3.预定义了一堆,嗯,一大堆函数和属性。


// 都能生效
console.log(Math.random());
console.log(this.Math.random());

   

4.作为全局变量的宿主。


var a = 1;
console.log(this.a);

   

5.客户端JavaScript中,全局对象有window属性指向自身。


var a = 1;
console.log(window.a);
 
this.window.b = 2;
console.log(this.b)

   

花了一个大篇幅介绍全局对象,其实就想说:

全局上下文中的变量对象就是全局对象呐!


函数上下文

在函数上下文中,我们用活动对象(activation object, AO)来表示变量对象。

活动对象是在进入函数上下文时刻被创建的,它通过函数的arguments属性初始化。arguments属性值是Arguments对象。

执行过程

执行上下文的代码会分成两个阶段进行处理:分析和执行,我们也可以叫做:

1. 进入执行上下文

2. 代码执行

进入执行上下文

当进入执行上下文时,这时候还没有执行代码,

变量对象会包括:

1. 函数的所有形参 (如果是函数上下文)

· 由名称和对应值组成的一个变量对象的属性被创建

· 没有实参,属性值设为undefined

2. 函数声明

· 由名称和对应值(函数对象(function-object))组成一个变量对象的属性被创建

· 如果变量对象已经存在相同名称的属性,则完全替换这个属性

3. 变量声明

· 由名称和对应值(undefined)组成一个变量对象的属性被创建;

· 如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性

举个例子:


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

   

在进入执行上下文后,这时候的AO是:


AO = {
    arguments: {
        0: 1,
        length: 1
    },
    a: 1,
    b: undefined,
    c: reference to function c(){},
    d: undefined
}

   

代码执行

在代码执行阶段,会顺序执行代码,根据代码,修改变量对象的值

还是上面的例子,当代码执行完后,这时候的AO是:

AO = {
    arguments: {
        0: 1,
        length: 1
    },
    a: 1,
    b: 3,
    c: reference to function c(){},
    d: reference to FunctionExpression "d"
}

   

到这里变量对象的创建过程就介绍完了,让我们粗略的总结我们上述所说:

1. 全局上下文的变量对象初始化是全局对象

2. 函数上下文的变量对象初始化只包括Arguments对象

3. 在进入执行上下文时会给变量对象添加形参、函数声明、变量声明等初始的属性值

4. 在代码执行阶段,会再次修改变量对象的属性值


思考题

最后让我们看几个例子:

1.第一题


function foo() {
    console.log(a);
    a = 1;
}
 
foo();
 
function bar() {
    a = 1;
    console.log(a);
}
bar();

   

第一段会报错:Uncaught ReferenceError: a is not defined

第二段会打印1。

这是因为函数中的”a”并没有通过var关键字声明,所有不会被存放在AO中。

第一段执行console的时候,AO的值是:


AO = {
    arguments: {
        length: 0
    }
}

   

没有a的值,然后就会到全局去找,全局也没有,所以会报错。

当第二段执行console的时候,全局对象已经被赋予了a属性,这时候就可以从全局找到a值,所以会打印1。

2.第二题


console.log(foo);
 
function foo(){
    console.log("foo");
}
 
var foo = 1;

   

会打印函数,而不是undefined。

这是因为在进入执行上下文时,首先会处理函数声明,其次会处理变量声明,如果如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性。


本文由职坐标整理发布,欢迎关注职坐标WEB前端JavaScript频道,获取更多JavaScript知识!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved