js的变量提升(预解析)

变量对象的创建过程是在当前执行上下文创建的时候;而变量的赋值是在当前执行上下文执行的时候。虽然我们常常在声明的同时赋值,但是声明和赋值并不是同一时间发生的,所以会出现变量提升的情况。

变量提升

变量提升是指,在变量对象创建的过程中经历了如下过程:

  • 建立arguments对象。检查当前上下文中的参数,建立该对象下的属性与属性值。
  • 检查当前执行上下文中的函数声明,即function关键字声明的,在变量对象中以函数名创建一个属性,属性值为指向该函数所在内存的引用,如果函数名已经存在则覆盖。
  • 检查当前上下文中的变量声明,即var关键字声明的,以变量名为属性名创建一个属性,属性值为undefined,如果有重复的属性名,为了防止同名函数被修改为undefined,则跳过。

具体过程

例一:

 	function test() { 
        console.log(foo); 
        console.log(bar); 
        var foo = 'Hello'; 
        console.log(foo); 
        var bar = function () { 
            return 'world'; 
        } 
        function foo() { 
            return 'hello'; 
        } 
    } 
    test();

在该段代码运行时,从最开始是全局执行上下文先入栈,然后函数被调用,函数的执行上下文被创建,此时函数内的变量对象被创建,首先function foo被声明,指向该函数在内存中的引用,然后var foo要被声明时发现与函数名重复跳过,然后var bar被声明指向undefined,到此创建变量对象就完成了,然后test()中建立作用域链并确定this的指向。
然后就是该函数执行上下文执行的阶段了,输出foo,输出bar,然后foo被赋值,此时再输出foo就是新的值。
所以运行结果如下:
在这里插入图片描述
例二:


    function test() { 
        console.log(foo); 
        console.log(bar); 
        var foo = 'Hello'; 
        console.log(foo); 
        function bar() { 
            return 'world'; 
        } 
        function foo() { 
            return 'hello'; 
        } 
    } 
    test();

这个例子和上一个唯一不同的就是,函数bar的声明方式,在例一中bar是匿名函数(var关键字声明的),在例二中是函数声明,两者的运行结果是不同的,这两个的对比可以体现出函数在变量提升时非同寻常的地位。
运行结果如下:
在这里插入图片描述
在该段代码中bar的值就不是undefined了。

ps:在没有进入执行阶段之前变量对象中的属性都不能被访问,在执行阶段时,变量对象变成活动对象,所有的属性就能被访问到了,变量对象和活动对象其实是同一个对象,只不过处于执行上下文的不同时期。

在ES6中

在 ES6 中,新增的 let 和 const 的关键字,不存在变量提升。

用这两个关键字声明时就可以按照我们的正常思维来写代码了,没有声明就不能被访问到。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值