手机版
你好,游客 登录 注册
背景:
阅读新闻

JavaScript变量提升的本质

[日期:2018-03-21] 来源:Linux社区  作者:smyhvae [字体: ]

变量提升

先说三句总结性的话:

  • let 的「创建」过程被提升了,但是初始化没有提升。
  • var 的「创建」和「初始化」都被提升了。
  • function 的「创建」「初始化」和「赋值」都被提升了。

所以,我们要注意,这三种变量提升,含义是不同的。

变量提升的规律

在进入一个执行上下文后,先把 var 和 function 声明的变量前置,再去顺序执行代码。

PS:作用域分为全局作用域和函数作用域,用var声明的变量,只在自己所在的所用域有效。

我们举例来看看下面的代码。

代码 1:

    console.log(fn);
    var fn = 1;

    functionfn() {
    }

    console.log(fn);

相当于:

    var fn = undefined;

    functionfn() {
    }

    console.log(fn);
    fn = 1;
    console.log(fn);

打印结果:

代码 2:

    console.log(i);
    for (var i = 0; i < 3; i++) {
        console.log(i)
    }

相当于:

    var i = undefined;

    console.log(i);
    for (i = 0; i < 3; i++) {
        console.log(i);
    }

打印结果:

代码 3:

    var a = 1;

    functionfn() {
        a = 2;
        console.log(a)
        var a = 3;
        console.log(a)
    }

    fn();
    console.log(a);

相当于:

    var a = undefined;

    functionfn() {
        var a

        a = 2
        console.log(a)
        a = 3
        console.log(a)
    };

    a = 1;
    fn();
    console.log(a);

打印结果:

声明时的重名问题

假设a被声明为变量,紧接着a又被声明为函数,原则是:声明会被覆盖(先来后到,就近原则)。

PS:

  • 如果a已经有值,再用 var 声明是无效的。
  • 如果a已经有值,紧接着又被赋值,则赋值会被覆盖

举例1:

    var fn;  //fn被声明为变量
    functionfn() {// fn被声明为function,就近原则

    }

    console.log(fn); //打印结果:function fn(){}

举例2:

    functionfn() {}  //fn被声明为function,且此时fn已经被赋值,这个值就是function的对象

    var fn;  //fn已经在上一行被声明且已经有值, 再 var 无效,并不会重置为 undefined

    console.log(fn)  //打印结果:function fn(){}既然再var无效,但是再function,是有效的:

    functionfn() {}  //fn被声明为function,且此时fn已经有值,这个值就是function的对象

    functionfn() {  //此时fn被重复赋值,会覆盖上一行的值
        console.log('smyhvae');
    }
    console.log(fn)

打印结果:

函数作用域中的变量提升(两点提醒)

提醒1:

在函数作用域也有声明提前的特性:

  • 使用var关键字声明的变量,是在函数作用域内有效,而且会在函数中所有的代码执行之前被声明
  • 函数声明也会在函数中所有的代码执行之前执行

因此,在函数中,没有var声明的变量都会成为全局变量,而且并不会提前声明。

举例1:

        var a = 1;

        functionfoo() {
            console.log(a);
            a = 2;    // 此处的a相当于window.a
        }

        foo();
        console.log(a);  //打印结果是2

上方代码中,foo()的打印结果是1。如果去掉第一行代码,打印结果是Uncaught ReferenceError: a is not defined

提醒2:定义形参就相当于在函数作用域中声明了变量。

        function fun6(e) {
            console.log(e);
        }

        fun6();  //打印结果为 undefined
        fun6(123);//打印结果为123

其他题目

    var a = 1;
    if (a > 0) {
        console.log(a);
        var a = 2;
    }
    console.log(a);

打印结果:

1

2

上方代码中,不存在块级作用域的概念。if语句中用var定义的变量,仍然是全局变量。

顺便延伸一下,用let定义的变量,是在块级作用域内有效。

本文永久更新链接地址https://www.linuxidc.com/Linux/2018-03/151490.htm

linux
相关资讯       JavaScript变量提升 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款