FireFox和FireBug的一个BUG
前几日,和朋友解说javascript预解析机制的时候,给了下面的示例代码:
var a = 1;
function a(){
alert(1111);
};
alert(a);
毫无疑问,结果应该是弹出1,简单的说,浏览器在执行JS代码时,第一步先扫描代码块,遇到var关键字,则提前至当前作用域的代码行的开头,接着扫描function声明,接在var之后,然后执行代码,于是上述代码真正执行时应是这样的:
var a ;
function a(){
alert(1111);
};
a = 1;
alert(a);
如果有疑问的同学可以参考ECMA文档,下面这个链接我网上搜的,不想去求证,只想理解机制的同学可以参考下:http://www.zhufengpeixun.com/jishujiangtang/javascriptjiangtang/2011-01-16/512.html
第一部分的代码,在FF、chrome、IE下运行都是显示1,没啥疑问,而我朋友在FireBug console下运行的时候,确弹出函数代码,也就是:
function a(){
alert(1111);
};
隐约记得半年前在网上看到一个老外的帖子说FireBug console是用eval执行输入的代码的,不过具体忘记了,最近去搜也没搜到。在这里个人推测下,FireBug是按语句一条一条eval的, 也就是上面代码变为:
eval('var a = 1');
eval('function a(){alert(1111);}');
eval('alert(a)');
而eval是将执行的语句加入到最近作用域中,按上述的方式,每条语句都是立即执行,自然就是弹出函数代码了。自此,FireBug的解析问题也许有一个推测的答案,希望有更权威的文献论证。
-------------------------------------------------华丽分割线-----------------------------------------------------------------
接着是FireFox下的Bug,同样是类似的代码,今天不知脑抽怎么的,居然会用这样的代码去测试,居然会测试出FF和IE8以及Chrome的不同执行结果,先不废话,代码如下:
{
var a = 1;
function a(){
alert(1111);
}
alert(a);
}
是的,你没看错,只是在最开始的代码上加入了两个大括号而已,JS是函数级作用域,以上从语法角度说,依然是在全局下运行,依然是应该弹出1,在Chrome14和IE8下运行也是如此,可是在FireFox6下运行,居然弹出的是函数代码,坑爹啊是不,弹出的是函数代码啊。。 蛋都碎了。。 这又是个什么情况?
推测1: 难道FireFox的JS引擎对花括号内的语句是一条一条解析的,而没有经过预解析过程?以下代码似乎推翻了这个推测:
if(0){
var a = 1;
function a(){
alert(1111);
}
alert(a);
}
alert(a)
上述代码在FF下,弹出的是undefined,说明a还是被预解析了,如果没有预解析,应该是报错的。
上述代码在chrome和IE8下,弹出的是函数代码,说明什么了? 不是太理解? 再加句,执行以下代码:
if(0){
var a = 1;
function a(){
alert(1111);
}
alert(a);
}
alert(a)
a();
以上代码在FF下执行,先弹出undefined,接着报错,提示a() is not a function;在IE8和Chrome下运行,弹出函数代码,以及1111,说明a()这个语句正常执行了。说明Chrome和IE8都扫描了var和function声明,但是因为if中的条件为假,所以a=1不会被执行,最终a是个function。 莫非FF把花括号内的函数声明当作函数表达式?这样的话确实不会预解析了。
于是有了推测2:
FF对JS语句的var关键字和其他浏览器一样,都是优先扫描,但是对语句块(花括号)内的function声明有着不同的处理,IE8和Chrome对语句块内的function声明同样是预解析处理, 而FF对语句块内的function声明则当作函数表达式,即上述代码中的函数声明在FF中翻译为:var a = function(){alert(1111);}; 这样做似乎可以对JS进行优化,比如上述的if语句,条件为假,内部代码理应不被执行,而在IE8和Chrome下确发现a居然是个函数,对未理解JS预解析机制的同学会造成莫大的迷惑。
至此,似乎FireFox下的Bug也有了一个似乎合理的解释。不过同样的,这两个解释都是推测,还是希望有权威的资料出来。
摘自 Exodia的专栏
补充:web前端 , JavaScript ,