美文网首页JS基础
js变量提升与函数提升

js变量提升与函数提升

作者: superzdd | 来源:发表于2017-03-23 00:49 被阅读0次

    从别人给我的一道题目说起,请问执行下面语句后的输出结果

    var a = 3;
    function test(){
      console.log(a);
      a(4);
      function a(b){
        a = b;
      }
      console.log(a);
    }
    console.log(a);
    test();
    

    我最初的答案是:

    3
    3
    4
    

    其实应该是

    3
    function a(b)
    4
    

    这道题包含了了函数提升与变量优先级的问题。为了更好地理解这个复合问题,我们一个一个说起。

    变量提升#

    意思是你代码中声明变量的所在行,其实并不是真正声明的地方,javascript编译时会统一将声明提升到作用域的最上方。

    比如当你写下这行代码时:

    var a = 3;
    

    编译器会将变量声明提升到代码顶部,但是赋值仍然在原来的地方,变为:

    var a;
    a = 3;
    

    举个例子:

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

    其输出结果为:

    3
    undefined
    

    因为其实际编译代码为

    var a,b;
    a = 3;
    console.log(a);
    console.log(b);
    b = 2;
    

    那现在问题升级一下,引入作用域的概念

    var a = 3;
    function test(){
      console.log(a);
      a = 4;
      console.log(a);
    }
    

    其结果为:

    3
    4
    

    恩,我不知道有没有迷惑到你,反正我被我自己迷惑到了,我们再来下一题

    var a = 3;
    function test(){
      console.log(a);
      var a = 4;
      console.log(a);
    }
    test();
    

    其结果为:

    undefined
    4
    

    这里要先说一下同名变量优先级,在同一作用域内,两个同名变量中,局部变量的优先级 > 全局变量的优先级,即test方法中的a会覆盖外部的a。

    再回到变量提升,所以test方法在编译后实际是这样的

    function test(){
      var a ; // 变量声明提升到方法顶部
      console.log(a);
      a = 4; // 赋值仍然在原处进行
      console.log(a);
    }
    
    

    变量作用域#

    所有不用var声明的变量都是全局变量
    在函数体内,同名的局部变量或参数优先级会高于同名局部变量,即

    var a = 3;
    function test() {
      var a = 4;
      console.log(a);
    }
    test();
    console.log(a);
    

    会输出

    4
    3
    

    函数提升#

    变量提升理解了,函数提升会好理解一些,函数的声明会提到作用域的顶端,但不同的是,函数提升会将其方法体的内容一起提升,举例来说

    function test(){
      test1();
      var b = 5;
      function test1(){
        console.log(b);
      }
    }
                
    test();
    

    会被编译为

    function test(){
      var b;
      function test1(){
        console.log(b);
      }
      test1();
      b = 5;
    }
                
    test();
    

    输出

    undefined
    

    函数声明方式分为两种,函数声明(函数式声明)和函数表达式(变量式声明),<b>只有函数声明才会执行函数提升</b>

    console.log(a);
    console.log(b);
    
    // 函数声明 执行函数提升
    function a(){}
    
    // 函数表达式 不执行函数提升 但可以看成是变量提升
    var b = function(){}
    

    输出

    function a()
    undefined
    

    最后,再看下这个问题

    var a;
    function a(){
      console.log(2);
    }
    
    console.log(a);
    

    结果到底会是undefined还是function?输出如下

    function a()
    

    那再加强一下

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

    输出

    function a()
    2
    3
    

    函数提升优先级比变量提升要高,且不会被变量声明覆盖,但是会被变量赋值覆盖。现在应该明白最上方那道题为什么会是这个结果了吧?其编译过程如下:

    var a;
    function test() {
        function a(b) {
            a = b;
        }
        console.log(a); // functing a(b)
        a(4);
        console.log(a); // 4
    }
    a = 3;
    console.log(a); // 3
    test();
    

    相关文章

      网友评论

        本文标题:js变量提升与函数提升

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