JavaScript函数x(){..}在`if';在Firefox中,而不是在Chrome和Opera中

JavaScript函数x(){..}在`if';在Firefox中,而不是在Chrome和Opera中,javascript,firefox,Javascript,Firefox,考虑以下JavaScript代码: (function(){ foo(); function foo(){ alert('Hello, World!'); } })(); 在Firefox、Opera和Chrome中,这与预期一样;我们接到警报。相比之下: (function(){ if (true){ foo(); function foo(){ alert('Hello, World!'); } } })(); Firefox3.6和4(beta版)(即两

考虑以下JavaScript代码:

(function(){
  foo();
  function foo(){ alert('Hello, World!'); }
})();
在Firefox、Opera和Chrome中,这与预期一样;我们接到警报。相比之下:

(function(){
  if (true){
    foo();
    function foo(){ alert('Hello, World!'); }
  }
})();
Firefox3.6和4(beta版)(即两者都使用SpiderMonkey)抛出一个异常:未定义foo

Chrome(即V8)和Opera(即Opera使用的任何引擎)按预期(由我)工作

哪一种行为是正确的,还是由实现来决定

FWIW,再次将其封装在函数中,再次使用FF很好:

(function(){
  if (true){
    (function(){
      foo();
      function foo(){ alert('Hello, World!'); }
    })();
  }
})();

这是由于不同的浏览器使用不同的symantec解析。通常对第一个声明进行求值。因为if条件封装了foo方法的声明,所以不解析它。理想情况下,您不应该创建运行时条件方法

foo在执行if语句之前不会被解析,甚至在定义它之前调用它的if语句中也是如此。虽然正如您所说,它在Chrome等浏览器中工作。如果我编写这样的代码,我会期望FF表现出的行为


出于可维护性的考虑,我希望您不要这样编写代码-这是一个混乱的局面。

为了安全起见,请以以下方式编写代码:

var foo=function(){alert('Hello,World!');} foo()

在(function(){})()块内,您将获得真正的私有方法。

根据,
SourceElement
被定义为:

SourceElement :
Statement 
FunctionDeclaration
因此,
FunctionDeclaration
s和
Statement
s是不同的。和块(例如,
if
)只能包含
语句
s:

Block :
   { StatementList opt }

StatementList :
   Statement
   StatementList  Statement
因此,根据规范,在
if
s中没有
函数声明。ECMA-262第3版和第5版第16节允许这样做。行为似乎由实现来决定

非标准
FunctionStatement
示例:

try {
  function Fze(b,a){return b.unselectable=a}
  /*...*/
} catch(e) { _DumpException(e) }
函数表达式的示例

var Fze;
try {
  Fze = function(b,a){return b.unselectable=a};
  /*...*/
} catch(e) { _DumpException(e) }
function aa(b,a){return b.unselectable=a}
函数声明的示例

var Fze;
try {
  Fze = function(b,a){return b.unselectable=a};
  /*...*/
} catch(e) { _DumpException(e) }
function aa(b,a){return b.unselectable=a}

我想你会在这里找到答案:谢谢你,菲利克斯。这让我想到了这里:请看,这是正确的:所有浏览器都实现了自己对ECMAScript标准的扩展,以处理块中的函数声明。