美文网首页
JavaScript变量提升

JavaScript变量提升

作者: viviChen | 来源:发表于2019-10-17 15:49 被阅读0次

    我们先提前预告一下变量提升的几个要点,然后在根据后面的例子进一步阐述:

    1. 变量提升是按照作用域为单位的;
    2. 函数的提升优先于变量的提升;
    3. 存在多个相同函数名的函数会被覆盖;
    4. 函数表达式并不会被提升。

    章节直通车:

    什么是变量提升

    可能有些小伙伴不清楚什么是变量提升,我们以一个简单的例子来说明一下:

    console.log( a );
    
    var a = 2;
    

    大家可以自己思考或者直接试验一下,这里打印的a为undefined。

    我们在第一章中说道编译器的基础三步骤,其一就是分词、词法分析,在此阶段编译器会把一些变量和相应的作用域进行关联,在作用域中提前声明,我们可以把上面的代码稍微变动如下:

    编译阶段:

    var a;
    

    执行阶段:

    console.log( a );
    
    a = 2;
    

    所以这时的a已经被定义,输出的时候就是undefined。这个就叫做变量提升

    变量提升是按照作用域为单位的

    foo();
    
    function foo() {
        console.log( a ); // undefined
    
        var a = 2;
    }
    

    在全局作用域中,foo函数被提升;
    在foo函数中,变量a被提升。

    console.log(c); // undefined
    
    if (true) {
        var c = 1;
    }
    

    注意,if的大括号并不是作用域,所以这里的作用域还是全局作用域,变量c被提升了。(上一章节有具体介绍JavaScript作用域)

    本来准备按照《你不知道的JavaScript》书中以if大括号和函数为例来说明,但是现在es6已经改变了这种做法,在if条件中的函数会默认为函数表达式,函数表达式并不会被提升如下:

    foo(); // "b"
    
    var a = true;
    if (a) {
       function foo() { console.log( "a" ); }
    }
    else {
       function foo() { console.log( "b" ); }
    }
    

    现在这里已经不像书中说的输出“b”了,而是undefined。

    当然对于老版本这种操作也是非常不友好的,并不推荐使用,这里只是提一嘴。

    函数的提升优先于变量的提升

    foo(); // 1
    
    var foo;
    
    function foo() {
        console.log( 1 );
    }
    
    foo = function() {
        console.log( 2 );
    };
    

    上面很清晰的可以看到函数foo的声明是优先于变量的,否则会报错TypeError。我们可以将上面的代码修改为提升后的样子:

    function foo() {
        console.log( 1 );
    }
    
    // var foo; 由于上面foo已经被声明了,这一条就被直接过滤了
    
    foo(); // 1
    
    foo = function() {
        console.log( 2 );
    };
    

    存在多个相同函数名的函数会被覆盖

    foo(); // 3
    
    function foo() {
        console.log( 1 );
    }
    
    var foo = function() {
        console.log( 2 );
    };
    
    function foo() {
        console.log( 3 );
    }
    

    相关文章

      网友评论

          本文标题:JavaScript变量提升

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