美文网首页
变量对象的生成

变量对象的生成

作者: shandamengcheng | 来源:发表于2020-04-03 09:15 被阅读0次

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

    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中出来,然后才可以正常访问。

    相关文章

      网友评论

          本文标题:变量对象的生成

          本文链接:https://www.haomeiwen.com/subject/cimcphtx.html