变量对象的生成

2020-04-03  本文已影响0人  shandamengcheng

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

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

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

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

VO与AO

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

在全局执行上下文中,变量对象就是全局对象。只有全局上下文的变量对象允许通过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中出来,然后才可以正常访问。

上一篇下一篇

猜你喜欢

热点阅读