在FireFox和FireBug中的一个Bug这篇文章中,偶然发现了FireFox下的函数声明问题,一直没有得到权威的资料来解决。11月26日面试新浪微博的时候,面试官也问到了这个问题,当然他没看我的BLOG,并从他口中得知,这个不是BUG,而是FF的Monkey引擎就是这样解析的,当然我的回答是:“个人推测,在FF下对语句快内的函数声明转化为函数表达式”。 面试官说不是,当然也没给出具体答案,提示我说MDN有这方面的资料。
如果懒得看前面的文章的话,可以看看下面一个简单的例子,在FF/IE/Chrome都跑一遍,看看FF和其他二者之间的差异:(FF会报错,其他的会弹出函数代码)
if(0){
function a(){}
}
alert(a);
当天晚上,我去找了找MDN,还真被我找到了,从资料上看,和我的推测是一致的,就是例子也和我前面提到的文章也类似。具体链接如下:
英文水平不是特别好,这里贴下重点部分和例子,并稍微翻译下(强烈建议看原文,我的翻译太蹩脚了):
函数声明式非常容易(并且常常出乎意料)转化为函数表达式。一个函数声明要么转化为一个表达式的部分,要么不再是一个函数或脚本本身的"source element"。"source element" 是脚本中或一个函数体内的非嵌套语句。
-
- varx=0;//sourceelement
- if(x==0){//sourceelement
- x=10;//notasourceelement
- functionboo(){}//notasourceelement
- }
- functionfoo(){//sourceelement
- vary=20;//sourceelement
- functionbar(){}//sourceelement
- while(y==10){//sourceelement
- functionblah(){}//notasourceelement
- y++;//notasourceelement
- }
- }
Examples:
-
- //functiondeclaration
- functionfoo(){}
- //functionexpression
- (functionbar(){})
- //functionexpression
- x=functionhello(){}
-
- if(x){
- //functionexpression
- functionworld(){}
- }
-
- //functiondeclaration
- functiona(){
- //functiondeclaration
- functionb(){}
- if(0){
- //functionexpression
- functionc(){}
- }
- }
函数可以用//函数语句//(一个ECMA-262 第3版允许的扩展)或者Function构造函数条件的定义。
在下面的脚本中, zero函数绝不会被定义并且不能够被触发,因为'if (0)'将它的条件判断为false:
- if(0){
- functionzero(){
- document.writeln("Thisiszero.");
- }
- }
注意:虽然这类函数看起来像函数声明,它实质上是一个语句,因为它被嵌套在另一个语句中。见函数声明和函数表达式的不同之处。
注意:一些JavaScript引擎,不包括SpiderMonkey(FF的JS引擎),不正确的将任何函数具名表达式当作函数声明。这将导致zero被定义,甚至条件总是假的时候。条件的定义函数的一个安全做法是定义匿名函数并将其分配给一个变量(译者注:其实就是用函数表达式):
- if(0){
- varzero=function(){
- document.writeln("Thisiszero.");
- }
- }
总结
MDN是很有价值的资料,有时间的话还真是需要去看看。