• 函数声明 和 var声明的优先级


    1.变量声明 提升:

    console.log(typeof a); // undefined
     
    var a = 1;
    
    console.log(typeof a); // number

      执行过程 相当于:

    var a;
    
    console.log(typeof a); // undefined
    
    a = 1;
    
    console.log(typeof a); // number

     

    2.函数声明 提升:

      函数声明 的提升是一个 整体提升的过程

    demo:

    console.log(typeof a); // function
     
    function a(){}
     
    console.log(typeof a); // function

      如上的demo,足可以证明,这一结论;假如不是整体提升,是类似于 var变量声明的提升的方式,应该会如 var变量声明的方式的输出方式相同, 先输出 undefined,再输出 function;

    3.无所谓 函数声明优先 or 变量声明优先

      那么,又来了个问题,既然 var声明 和 函数声明 都有提升机制,那么它俩的声明提升优先级是什么样子呢;

    为了论证这个我在网上看了好多资料,也查了好多书籍,大家一直认为 函数声明提升 优先于 变量声明提升,但是我发现,大家的论据都不够充分;比如如下的一个论证:

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

      然后,也描述了它的执行过程,相当于:

     解释 A:

    function a(){
        console.log(1);
    }
    var a; // 遇到没有赋值的同名声明,忽略,不做操作;相当于什么都没有做
    
    a(); // 1
    
    a = function(){
        console.log(2);  
    }
    
    a(); // 2

      如果如上的操作的解释,也可以通过,可以论证出 “函数声明提升 优先于 变量声明提升”;但是,按如下的理解应该也是解释的通的啊:

    解释 B:

    // 注意 var a 和 function a声明都会在栈空间开辟存储空间,并且 是占用同一块name为 a的空间;
    
    var a; // 此时 a 没有赋值, 是个空的栈空间值
     
    function a(){ // 找到 name为a的栈空间,给它赋值 function(){console.log(1)}, 相当于覆盖
        console.log(1);
    }
    
    a(); // 1
    
    a = function(){
        console.log(2);  
    }
    
    a(); // 2

      看到了吧,如上的 论述也是行的通的,但是论述出来的结果 是“变量声明提升 优先于 函数声明提升”;这就尴尬了。。。

    其实呢,我仔细想了一下,其实 谁先声明提升的都无所谓,因为 “var a 和 function a声明都会在栈空间开辟存储空间,并且开辟的是同一块 name为 a的空间,也就是说它们用的是同一块空间”;

    4.函数声明先赋值,变量声明执行到赋值语句才赋值

      因为两种声明方式共同操作一块栈空间,所以,主要看是谁先赋值的,我们再看一个例子:

    console.log(typeof a); // function
    
    var a = 1;
    
    function a(){}
    
    console.log(typeof a); // number

      这就看的出来了,通过上边的这个demo, 明显可以看出来,应该 函数声明先赋值的,它是在执行上下文的执行阶段一开始的时候就已经进行了赋值操作,所以 最开始 typeof a 可以得到 function;而,变量声明 是要执行到赋值语句的时候才进行的赋值,所以 最后 typeof a 得到是 number;

      如果不是这样的话,我们不妨做下假设:

      假设1:都是最早赋值,不管谁先赋值,结果如下:

    /*
    ->var 声明;
    
    ->函数声明;
    
    ->var 赋值;
    
    ->函数赋值:
    
    ->console.log(typeof a); // function 或者 number
    
    ->console.log(typeof a); // function 或者 number
    */

      结果如上,最后输出不是同是 function 就是同是 number, 不符合正确输出;

      假设2:都是执行到赋值语句的时候才赋值,无论 两种声明 谁前谁后,结果如下:

    /*
    ->var 声明;
    
    ->函数声明;
    
    ->console.log(typeof a); // undefined
    
    ->赋值操作:
    
    ->console.log(typeof a); // function 或者 number
    */

      结果如上,第一个输出一定都是 undefined, 不符合正确输出;

      假设3:通过 (1) 和 (2)的不通过,那么只剩下一种可能了,都是先声明,然后一个先赋值,一个到 执行语句的时候才赋值;也就推测出了我们的结论:"函数声明先赋值,变量声明直到赋值语句的时候才赋值";执行过程如下:

    /*
    -> a 声明;// 因为同用一个栈空间,所以无所谓谁先声明
    
    -> 函数声明赋值
    
    ->console.log(typeof a); // function
    
    ->变量声明赋值:
    
    ->console.log(typeof a); // number
    */

      符合正确输出的结果;所以结论成立;

      其实 函数的整体提升方式就已经论证了这一点,无论是如 解释 A 函数提升优先 + 忽略未赋值的 var 声明, 还是如 解释 B变量声明提升优先 + 函数后声明覆盖var 声明,最后都是在同一个栈空间上进行的操作,并无所谓,重要的是谁先进行的赋值操作;还有就是如上的这种 变量声明和函数声明是同名的用法,尽量不要在正式开发中使用,很容易就出现难以排查的异常;

    4.总结

      *->1.函数声明 和 变量声明都有声明提升机制

      *->2.函数声明 是整体提升的方式,来进行的声明提升;

      *->3.函数声明 和 变量声明,无所谓谁优先于谁,都是在预编译阶段进行的;(根据第4点的总结,也可以理解为 函数声明优先于变量声明)

      *->4.函数声明赋值 要早于 函数声明赋值

        **->.函数声明赋值,是在执行上下文的开始阶段进行的;

        **->.变量声明赋值,是在执行到赋值语句的时候进行的赋值;

      

     原创:转载注明出处,谢谢 :)

     

  • 相关阅读:
    mysql查找有某列但没有此列索引的表
    mysql找到所有索引
    mysq在某一刻同时获取主从库的位置点
    新书《深入应用C++11:代码优化与工程级应用》出版,感谢支持
    c++11实现一个简单的lexical_cast
    应该用bind+function取代虚函数吗?
    《深入应用C++11:代码优化与工程级应用》开始发售
    一个更好的C++序列化/反序列化库Kapok
    C++技术沙龙主要内容
    C++11模版元编程
  • 原文地址:https://www.cnblogs.com/cnblogs-jcy/p/8926310.html
Copyright © 2020-2023  润新知