美文网首页
【知识点】声明提升

【知识点】声明提升

作者: 李李李李李晓华 | 来源:发表于2019-03-18 23:22 被阅读0次

    为了让大家更好的感受今天的内容,今天还是先以几道面试题开头吧。
    记得先给自己做出一个答案,然后再看文章看看思路对不对哦。

    1. 来一道基础的吧~
    var a="Hello";  
    function test(){  
      alert(a); 
      var a="World";
      alert(a);
    }
    test();
    
    1. 难度+1
    var a = 1;
    function outer(){ 
      a = 2; 
      function inner(){       
          alert(a); 
          a = 4; 
      } 
      inner();
    } 
    outer(); 
    alert(a);
    
    
    1. 继续加油
    (function(){
      f1(); 
      f2();
      var f1 = function(){};
      function f2(){
          alert(1);
      }
    })();
    
    1. 最后一道
    (function () {
       console.log(a);
       var a=1;
       function a() {
           console.log("biu~");
       }
    })()
    

    • 什么是声明提升

    引擎在解释JS代码之前,首先要对JS代码进行编译,其中编译的一部分工作就是找到所有的声明,包括变量和函数的所有声明都会在任何代码被执行前首先被处理。
    上一篇文章我曾经说过,var a = 1这句话会被浏览器读成 var aa = 1两句话执行,其中var a会在编译阶段就先执行了,而a = 1这段赋值代码会在原地等待执行阶段。

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

    上边这段代码,如果代码按照顺序由上自下执行,那么执行到console.log(a);时,a还没有声明,所以会包一个找不到变量a的错,但是事实上,这句话打印了一个undefined,说明a被声明了,但是没有被赋值,那么结合上一段的文字,我们可以得出代码实际运行的是这样的:

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

    • 函数的提升

    大家可能在书写代码的时候发现,无论函数封装写在前或者后,我们的函数调用都可以顺利执行。

    fn1();//可以执行
    function fn1() {
        console.log("hello");
    }
    

    为什么呢?其实函数声明,包括函数的代码块都i会被提升,所以调用函数的时候,函数声明已经被执行过了。

    但是有个案例大家了解一下:

    fn2();//报错,fn2不是一个函数
    var fn2 = function () {
       console.log("world");
    }
    

    我们可以看到 以给匿名函数赋值的形式定义函数,只会提升函数声明,但是函数表达式却不会被提升。因为变量fn2被提升,但是并没有赋值,我们书写的fn2()无法运行,而抛出了异常。
    以下就是实际执行的顺序:

    var fn2;
    fn2();
    fn2 = function () {
       console.log("world")
    }
    

    • 函数优先提升

    我们都知道了,函数声明和变量声明都会被提升,那么遇到这样的情况会怎么办?

    fn3();
    var fn3=function () {
        console.log("fn3-1");
    }
    fn3();
    function fn3() {
        console.log("fn3-2");
    }
    

    哎呦,嘛情况,突然迷了!!!
    这个时候你就要考虑,同样的一个变量名称,到底是把var fn3给先提声上去,再提升 fn3函数体?还是先提升 fn3函数体,再提升var fn3???其实都不对!!!

    答案是函数会被优先提升,但后才是变量提升,但是当函数提升后,然后发现还有一个变量声明和函数声明一样的名称,这个就是上一篇文章说的重复声明,那么这个var fn3 是不生效直接忽略的。

    所以实际代码运行顺序是:

    function fn3() {
       console.log("fn3-2");
    }
    fn3();//fn3-2
    fn3=function () {//var fn3因为重复声明被忽略
       console.log("fn3-1");
    }
    fn3();//fn3-1
    

    当然,我们还是建议再同一个作用域重复声明是很烂的选择

    • 说在最后

    再代码作用域中的声明,都会在代码执行前被首先处理,所有的声明都会被移动到各自作用域的最顶端,这个过程就叫做声明提升


    答案:

    问题1:

    var a="Hello";  
    function test(){  
      alert(a); 
      var a="World";
      alert(a);
    }
    test();
    

    实际执行:

    var a="Hello";
    function test(){
       //作用域有声明a,声明提升到这里
       var a;
       alert(a);//本作用域声明a,所以不去使用父作用域的a,但是本作用域的a没有赋值,所以弹出undefined
       a="World";
       alert(a);//赋值后 ,弹出world
    }
    test();
    

    问题2:

    var a = 1;
    function outer(){ 
      a = 2; 
      function inner(){       
          alert(a); 
          a = 4; 
      } 
      inner();
    } 
    outer(); 
    alert(a);
    
    

    执行结果:

    var a = 1;
    function outer(){
       a = 2;
       function inner(){
           //本作用域没有声明a,所以没有任何提升,直接执行
           alert(a); // 所以弹出 a为 2
           a = 4;
       }
       inner();
    }
    outer();
    alert(a);//只有全局声明了a,所以所有作用域使用的都是全局的a,所以a最后被赋值为4 弹出4
    

    问题3

    (function(){
      f1(); 
      f2();
      var f1 = function(){};
      function f2(){
          alert(1);
      }
    })();
    

    实际执行结果:

    (function(){
       function f2(){
           alert(1);
       }
       var fn1;
       f1();//提升后先执行fn1(),但是fn1被提升的是变量不是函数,所以这里报错,不是一个函数
       f2();//上一句话报错,这句话不再运行
       f1 = function(){};
    })();
    

    问题4:

    (function () {
       console.log(a);
       var a=1;
       function a() {
           console.log("biu~");
       }
    })()
    

    实际执行结果:

    (function () {
       function a() {
           console.log("biu~");
       }
       console.log(a);//打印了a这个函数的函数体
       a=1;//因为函数有限声明提升,所以这里的var a被提升时,发现重复声明,故被忽略了var a;    
    })()
    

    好了很晚了,古德奈特,有什么不懂的可以随时留言~ 喜欢请点赞~~~


    拜拜,晚安

    相关文章

      网友评论

          本文标题:【知识点】声明提升

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