zoukankan      html  css  js  c++  java
  • 一个讨论引发关于js中函数声明,函数表达式,形参与变量声明赋值引发的一些事

    这篇文章写的是关于一个讨论的一些东西,算是整理和学习!。讨论来源一个强大的前端群,群主 司徒正美(博客:http://www.cnblogs.com/rubylouvre/  微博:http://weibo.com/jslouvre?topnav=1&wvr=5&topsug=1)发了这样一个代码片段:

    先说说我自己第一反应的答案吧:

    1 function a(){}
    2 undefined
    3 [1,2,3]
    4 ee
    5 444
    6 6

    先说说我自己一开始最基本的理解吧:

    在函数中变量的声明会被提前,但赋值会到代码所在行才会进行,另外函数名只是一个指针而不是绑定的,是可以修改的,因为函数本身就是一个对象(可以参考:http://www.cnblogs.com/zhouyongtao/archive/2012/11/19/2776776.html)。

    a,aa变量的声明被提到代码的最前面此时值为undefined,但接着a指向了一个函数,故console.log(a)输出为function a(){},而console.log(aa)输出undefined,console.log(arguments)输出就为:[1,2,3]。

    然后a,aa,arguments均被赋值,故console.log(a)输出为:ee,console.log(aa)输出为:444,console.log(arguments)输出为:6。

    事情到这就真的完了吗?事实上远远没有完。

    有人说:“这里面参数的优先级低于变量声明和函数声明,所以一直被派上用处”。还有人说:“知识点:函数,形参,变量同名的话,通俗理解,函数>形参>变量”。

    那么函数声明,变量声明,赋值,如果有同名情况出现和这几者之间到底是谁优先呢?或者说谁覆盖谁?

    后来大佬又发话了。

    看完不能很好的理解,感觉抽象了。后来又有人贴出这样一篇正妹的文章:http://chauvetxiao.com/bo-blog/read.php?1

    其中有几个demo很不错,引用过来理解和验证一下大佬所说的东西还是特别有帮助的。(下面的demo大多数出自于正妹的文章)

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

    这个demo和上面那个例子验证了大佬的第一句话“变量声明,当变量声明遇到VO中已经有同名的时候,不会影响已经存在的属性”。

    第二句和第三句就不解释了。因为从上面第一例子已经看得出来了。

    但第四句后半句觉得不是很对。疑问来源于这样的两个demo

    1 function a(){
    2     console.log('2');
    3 }
    4 var a;
    5 console.log(a);//function a(){console.log('2);}
    1 function a(){
    2     console.log(a);
    3     var a=2;
    4 }
    5 a();//undefined

    那么在函数内部和全局环境中,是谁覆盖谁?其实第一个例子中,声明与变量声明是先后进行,而第二例子中是函数声明先进行,调用函数函数时再有变量的声明。所以前者输出的正如大佬所说是function a(){consoleo.log('2')},后者是undefined。

    另外也发现一点东西,js中全局变量的声明并不会提前。断点调试就能发现在window对象并没有这样一个属性。

    1 console.log(num);//错误
    2 num=2;

    这样的话,这个例子也比较容易弄懂。

     1 var num1 = 1;  
     2     
     3 function   fn(num3){  
     4     
     5     console.log(num1);    //output    undefined  
     6     
     7     console.log(num3);    //output  4  
     8     
     9     console.log(num4);    //throw error  “num4 is not defined”  
    10     
    11     console.log(num2);    //throw error  “num2 is not defined”  
    12     
    13     var num1 = num4 = 2;  
    14     
    15     num2 = 3;  
    16     
    17     var num3= 5;  
    18     
    19 }  
    20     
    21 fn(4);  

    如果理解了上面的东西,这样的demo也很容易搞懂了。

     1 function   fn(t){  
     2     
     3     t();  
     4     
     5     function t(){  
     6     
     7         console.log(2);  
     8     
     9     }  
    10     
    11     var t = function(){  
    12     
    13         console.log(3);  
    14     
    15     }  
    16     
    17 }  
    18     
    19 fn(function(){console.log(1)});  //output  2  

    另外也学到一个东西,对于块级作用中的函数声明在chrome和ie下会提前,而在firefox中,招待时才会进行。

     1 console.log(fn.toString());  
     2     
     3 if (true) {  
     4     
     5    function fn(){ return 1; }  
     6     
     7 }else {  
     8     
     9    if(false){  
    10     
    11       function fn(){ return 2; }  
    12     
    13    }  
    14     
    15 } 

    chrome和Ie下输出function fn(){return 2;}

    而firefox中抛出异常。

    如果不是很懂,再看这个例子。

     1 if (true) {  
     2     
     3     function fn(){ return 1; }  
     4     
     5 }else {  
     6     
     7      if(false){  
     8     
     9        function fn(){ return 2; }  
    10     
    11      }  
    12     
    13 }  
    14     
    15 console.log(fn.toString()); 

    chrome和ie一均为function fn(){ return 2;},而firefox中依然报错。

    可见三者处理并不相同。ff中会提前变量的声明,但不会提前块级作用域中的函数声明。而chrome和ie下就会提前块级作用域中的函数声明,而且后面的声明会覆盖前面的声明。

     

  • 相关阅读:
    第二周选答题-myod
    第六周实验-模块与系统调用
    2019-2020-11 20199313《Linux内核原理与分析》第十二周作业
    2019-2020-1 20199313《Linux内核原理与分析》第十一周作业
    2019-2020-1 20199313《Linux内核原理与分析》第九周作业
    2019-2020-1 20199313《Linux内核原理与分析》第八周作业
    20199322 2019-2020-2 《网络攻防实践》第4周作业
    20199322 2019-2020-2 《网络攻防实践》第三周作业
    20199322 2019-2020-2 《网络攻防实践》第2周作业
    20199322 2019-2020-2 《网络攻防实践》第一周作业
  • 原文地址:https://www.cnblogs.com/zhouyongtao/p/2783089.html
Copyright © 2011-2022 走看看