变量对象的生成


执行上下文的生命周期分为两个阶段:创建阶段和代码执行阶段。
创建阶段:

  1. 生成变量对象
  2. 确定作用域链
  3. 确定this的指向

生成变量对象的过程如下:

  • 建立arguments对象:检查当前上下文中的参数(函数参数),建立该对象下的属性和属性值。
  • 函数中的所有形参加入到变量对象中。

函数参数名作为一个变量对象的一个属性被创建,值为对应传进来的值 ,否则为undefined.

  • 当前执行上下文中的函数声明的提升,函数名作为变量对象的一个属性被添加,值为函数的引用。如果变量对象中存在一个同名函数,则会对前一个函数进行覆盖。
  • 变量提升。以变量名为变量对象的一个属性被添加,值为undefined。如果变量对象中存在一个同名函数命,那么该变量名不会影响到函数名。(可以理解为:重名的变量名不会再被添加进变量对象了)

VO与AO

VO为变量对象,AO为活动对象,其实,他们是同一个对象的两种状态,就是说,在执行上下文的创建阶段会生成VO,在执行上下文的代码执行阶段,VO就变成了AO。

  • 函数表达式不包含在VO中
  • 没使用Var声明的变量不包含在VO中

在全局执行上下文中,变量对象就是全局对象。只有全局上下文的变量对象允许通过VO的属性名称间接访问;函数执行上下文中,VO是不能直接访问的,此时AO代替了VO,从而通过AO来访问。

有一点需要注意

不使用var声明的变量是一个全局变量,那么只有在通知了系统这是一个全局变量之后才能访问。

更具体地说,其实不使用var创建的变量,即下面的代码中的这种方式创建的,是相当于给全局对象global添加了一个属性。由于全局对象是共享的,因此只有在属性添加之后才可以访问,否则会报错。

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

foo(); //Uncaught ReferenceError: a is not defined。

关于执行上下文中的非匿名立即执行函数

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

这段代码的执行结果为:

ƒ foo() {
    foo = 10
    console.log(foo)
}

这个可以理解为:在()中创建了一个变量对象,里面有一个foo属性,执行一个函数,在函数内部可以访问到这个foo属性,但是这个foo是只读的,因此赋值改写被忽略,因此结果为foo这个函数。

关于let和var

JS引擎在扫描代码发现变量声明时,要么将他们提升至作用域顶部(遇到var声明),要么将他们放入TDZ(遇到let和const声明)。访问TDZ中的变量会触发运行时错误。只有执行过变量声明语句后,变量才会从TDZ中出来,然后才可以正常访问。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值