深入理解javascript系列(四):变量对象(VO)1

在系列(三)中,我们提到了“执行上下文的生命周期”,现在我们来回顾一下:

当一个函数被调用时,一个新的执行上下文就会被创建。一个执行上下文的生命周期大致可以分为两个阶段:创建阶段和执行阶段。

创建阶段

在这个阶段,执行上下文会分别创建变量对象,确认作用域链,以及确定this的指向。

执行阶段

创建阶段之后,就开始执行代码,这个时候会完成变量赋值、函数引用、以及执行其它可执行的代码。

我们在系列(二)中也曾提到过变量对象(Variable Object),我们在javascript代码中声明的所有变量都保存在变量对象中,除此之外,变量对象中还有可能包含以下内容:

1、函数的所有参数。

2、当前上下文中的所有函数声明(通过function声明的函数)。

3、当前上下文中的所有变量声明(通过var声明的变量)。

说了这么多次变量对象,那到底什么才是变量对象了?希望通过本次系列的学习,我能理解变量对象这个概念。

4.1  创建过程

变量对象的创建,依次经历了以下几个过程。

1. 在Chrome浏览器中,变量对象会首先获得函数的参数变量及其值;在FireFox浏览器中,是直接将参数对象argument保存在变量对象中。

2. 依次获取当前上下文中所有声明的函数,也就是使用function关键字声明的函数。在变量对象中会以函数名建立一个属性,属性值为指向该函数所在的内存地址引用。如果函数名的属性已经存在,那么该属性的值会被新的引用覆盖。

3.依次获取当前上下文中的变量声明,就是使用var关键字声明的变量。每找到一个变量声明,就在变量对象中就以变量名建立一个属性,属性值为undefined,是undefined的哦。如果该变量名的属性已经存在,为了防止同名函数被修改为undefined,则会直接跳过,原属性值不会被修改。

注意:ES6支持新的变量声明方式let/const,规则与ar完全不同,他们是在上下文的执行阶段开始执行的,避免了“变量提升”带来的一系列问题,因此这里暂时先不介绍。

知道了上面的规则后,我们来思考一个问题,当我们执行以下代码时,具体的执行过程是怎么样的呢?

var a = 30;复制代码

首先,上下文的创建阶段会先确认变量对象,变量对象会获取带var关键字变量,他会以变量名a建立一个属性,属性值为undefined。因此第一步是:

var a = undefined;复制代码

上下文的创建阶段完毕后,开始进入执行阶段,在执行阶段需要完成变量赋值的工作,因此第二步是:

a = 30;复制代码

需要注意的是,这两步分别是执行上下文的创建阶段和执行阶段完成的。因此var a = undefined 这一步其实是提前到了比较早的地方去执行了(我们把这一过程叫做变量提升(Hoisting))。下面通过一个简单的例子来证明。


结合之前的理解,这个例子实际的执行顺序应该是:

//这个执行上下文 变量对象的创建阶段
var a = undefined;

//执行阶段
a = 30;复制代码

我们在4.1的创建过程的规则中,可以看出,在变量对象的创建过程中,函数声明的执行优先级会高于变量声明,而且同名函数会覆盖函数与变量,但是同名的变量并不会覆盖函数。

但是在上下的执行阶段,同名的函数会被变量重新赋值。

如果您觉得上面的话,不是那么好理解,我们通过一个实例来感受一下


请仔细看这段代码.

感受完了上面这张图,我们来看下代码的执行顺序:

//本执行上下文的变量对象的创建阶段
function fn() { console.log('fn') };
function fn() { console.log('new fn') };
function a() { console.log('a is func') };
var a = undefined;
var fn = undefined;

//执行阶段
a  = 20;
console.log(a); //20;
fn(); //'new fn';
fn = 'i am not a func';
console.log(fn);

复制代码

根据输出结果可以证明,在创建阶段,后创建的函数fn会覆盖前面创建的函数fn,但是变量fn并没有在创建阶段覆盖函数fn(注意我说的是创建阶段)。而在执行阶段,a与fn的重新赋值导致他们发生了变化。


请注意这张图,他为什么会报错?

或许您能一眼看出来,因为fn重新赋值覆盖后,fn就不是一个函数的引用地址了。fn()肯定会报错。

那么问题就在这里,为什么变量对象的创建阶段。变量fn = undefined 不会覆盖之前的已声明的函数fn了?如果您知道,希望您能在评论区下您的答案。

记住:执行上下文的两个阶段、变量对象创建的3条规则。

这些都是我以往的学习笔记。如果您看到此笔记,希望您能指出我的错误。有这么一个群,里面的小伙伴互相监督,坚持每天输出自己的学习心得,不输出就出局。希望您能加入,我们一起终身学习。欢迎添加我的个人微信号:Pan1005919589


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值