这篇文章写的是关于一个讨论的一些东西,算是整理和学习!。讨论来源一个强大的前端群,群主 司徒正美(博客: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下就会提前块级作用域中的函数声明,而且后面的声明会覆盖前面的声明。

 

 

posted on 2012-11-22 19:39  Icrt  阅读(4227)  评论(5编辑  收藏  举报