美文网首页
JS预解析

JS预解析

作者: 潘肚饿兵哥哥 | 来源:发表于2020-09-08 23:33 被阅读0次

    \color{rgba(254, 67, 101, .8)}{预解析}

    javascript代码是通过浏览器中的javascript解析器来执行的,javascript解析器在运行javascript的时候分为两步:预解析和代码执行

    1.没有声明变量,会报错

    console.log(num); 
    

    2.不报错,返回undefined

    console.log(num);
    var num = 10; 
    

    3.自定义函数:fn();在函数体的下面或上面调用都能正常返回结果11

    fn();
    function fn(){
       console.log(11);
    }
    //fn();
    

    4.声明函数:fun();在函数体上面调用函数体会报错,在下面调用就能正常显示结果

    fun();//这里调用有问题
    var fun = function(){
       console.log(22);
    }
    //fun();这里调用没问题,能正常返回22
    
    image.png

    \color{rgba(254, 67, 101, .8)}{预解析:JS引擎会把JS里面所有的var和function提到当前作用域的最前面}
    \color{rgba(254, 67, 101, .8)}{预解析完毕之后,按照代码书写的顺序从上往下执行}

    \color{rgba(254, 67, 101, .8)}{变量提升:}

    \color{rgba(254, 67, 101, .8)}{预解析分为变量预解析(变量提升)和函数预解析(函数提升)}

    1.变量提升:就是把所有的\color{rgba(254, 67, 101, .8)}{变量声明}提升到\color{rgba(254, 67, 101, .8)}{当前的作用域}最前面,不提示赋值操作

    根据这个原理,来看之前上面的第例子2:

    console.log(num);
    var num = 10; 
    //相当于按以下顺序执行:
    var num;
    console.log(num);
    num = 10; 
    

    当预解析把变量声明提到前面去之后,因为没有赋值,所以就会返回undefined

    \color{rgba(254, 67, 101, .8)}{例子4:}

    例子4的问题

    fn();//这里调用有问题
    var fun = function(){
      console.log(22);
    }
    //相当于执行了以下代码:
    var fun;//这里是相当于声明了一个变量
    fun();//这里是相当于调用了一个函数,而这个函数上面没有声明
    fun = function(){
       console.log(22);
    }
    

    这个函数调用之所以放在函数体下面就不会报错是因为执行顺序是先赋值,再调用,是以下顺序:

    var fun;
    fun = function(){
       console.log(22);
    }
    fun();
    

    \color{rgba(254, 67, 101, .8)}{函数提升:就是把所有的函数声明提升到当前作用域的最前面,不调用函数}

    之所以例子3的函数调用无论放在上面还是下面都不会出问题,就是因为他会把函数声明(在这个例子中,函数声明就是整个函数体)提到最前面,所以,无论函数调用在上还是在下,都会被提到最前面,所以不会出问题,因为例子3是自定义函数

    自定义函数的函数提升就是提升整个函数体
    而声明式函数的函数提升是把那个变量提升了(声明式函数提升的是函数表达式,就是那个变量,而函数的值其实就是整个函数体)

    \color{rgba(254, 67, 101, .8)}{预解析案例}
    \color{rgba(254, 67, 101, .8)}{案例1:结果是几}

            var num = 10;
            fun();
    
            function fun() {
                console.log(num);
                var num = 20;
            }
            //相当于执行了以下操作
            var num; //这是10的变量名,20的只提升到函数内部
            //然后整个函数体也会被提升到前面去
    
            function fun() {
                var num;
                console.log(num);
                num = 20;
            }
            num = 10;
            fun();
    

    这里提升后的执行顺序是:
    1.先执行第一行代码var num;没问题
    2.再执行函数体,函数体没有被调用,继续往下执行
    3.执行到num=10;此时num有值了,继续执行下去
    4.执行到fun();调用了函数,然后返回去执行函数体
    5.函数体中又有一个var num;
    6.这个函数体里console.log(num);的num根据作用域链会去找赋值的num,根据就近原则,先找到函数内部声明的num;
    7.函数内部的这个num只有声明,没有给值。所以返回undefined

    image.png

    \color{rgba(254, 67, 101, .8)}{案例2:结果是几}

            var num = 10;
    
            function fn() {
                console.log(num);
                var num = 20;
                console.log(num);
            }
            fn();
    
            //相当于按以下顺序执行代码
    
            var num;
    
            function fn() {
                var num;
                console.log(num);
                num = 20;
                console.log(num);
            }
            num = 10;
            fn();
    

    1.首先执行var num;,然后函数体没有调用不执行
    2.执行到num=10;之后执行函数调用
    3.然后继续执行函数体
    4.函数体中第一个num的值根据就近原则,是没有赋值的num,所以返回undefined
    5.第二个num,根据就近原则,num=20,所以第二个num值是20

    \color{rgba(254, 67, 101, .8)}{案例3:结果是 几}

            var a = 10;
            f1();
    
            function f1() {
                var b = 9;
                console.log(a);
                console.log(b);
                var a = '123';
            }
    
            //预解析为以下代码
            var a;
    
            function f1() {
                var b;
                var a
                b = 9;
                console.log(a);
                console.log(b);
                a = '123';
            }
            a = 10;
            f1();
    
    image.png

    \color{rgba(254, 67, 101, .8)}{案例4:答案是几}

            f1();
            console.log(c);
            console.log(b);
            console.log(a);
    
            function f1() {
                var a = b = c = 9;
                console.log(a);
                console.log(b);
                console.log(c);
            }
    
            //预解析为以下代码
            //var a = b = c = 9;世界上是:var a = 9; b = 9; c = 9;所以此时b、c是全局变量
            //集体声明: var a=9, b=9, c=9;用逗号隔开才是三个var
    
            function f1() {
                var a;
                a = b = c = 9;
                console.log(a);
                console.log(b);
                console.log(c);
            }
    
            f1();
            console.log(c);
            console.log(b);
            console.log(a);
    

    1.首先函数不执行不调用,然后到下面调用后返回执行函数体
    2.然后var a;然后a b c直接赋值了
    3.在函数内调用的a b c都是9
    4.最后到函数外部执行外面的log
    5.第一个c是全局变量,所以也是9
    6.第二个b也是全局变量,所以还是9
    7.第三个a是局部变量,外部不能调用,所以是undefined

    image.png

    相关文章

      网友评论

          本文标题:JS预解析

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