【问题标题】:JavaScript function x(){..} treated as var x=function(){..} inside `if' in Firefox, not in Chrome and OperaJavaScript 函数 x(){..} 在 Firefox 中的“if”中被视为 var x=function(){..},而不是在 Chrome 和 Opera 中
【发布时间】:2011-03-07 18:00:58
【问题描述】:

考虑以下 JavaScript 代码:

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

在 Firefox、Opera 和 Chrome 中,这符合预期;我们收到警报。现在对比一下:

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

Firefox 3.6 和 4(测试版)(即两者都使用 SpiderMonkey)抛出异常:foo is not defined

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

哪个是正确的行为,还是由实现来决定?

FWIW,再把它包在一个函数里,再去FF就好了:

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

【问题讨论】:

标签: javascript firefox


【解决方案1】:

根据the ECMA-262 5th Edition specSourceElement定义为:

SourceElement :
Statement 
FunctionDeclaration

所以,FunctionDeclarations 和 Statements 是不同的。并且块(例如if)只能包含Statements:

Block :
   { StatementList opt }

StatementList :
   Statement
   StatementList  Statement

因此,根据规范,从语法上讲,ifs 中没有 FunctionDeclarations。但是,根据the comp.lang.javascript FAQ, Mozzila browsers and others implement a "function statement"。这在 ECMA-262 第 3 版和第 5 版的第 16 节中是允许的。Spidermonkey adds FunctionStatement. JScript adds FunctionDeclaration, however, JScript also has JScriptFunction. 看来该行为由实现决定。

非标准FunctionStatement示例:

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

FunctionExpression 的示例:

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

FunctionDeclaration 的示例:

function aa(b,a){return b.unselectable=a}

【讨论】:

  • 这是正确的:所有浏览器都实现了自己的 ECMAScript 标准扩展,以处理块内看起来像函数声明的内容。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    foo 在执行 if 语句之前不会被解析 - 甚至在 if 语句中你在定义它之前调用它。尽管正如您所说,它适用于 Chrome 等。如果我编写这样的代码,我希望 FF 表现出的行为。

    为了可维护性,我希望您不要编写这样的代码 - 那是一团混乱。

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

        猜你喜欢
        • 2023-03-21
        • 1970-01-01
        • 1970-01-01
        • 2018-11-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-12
        • 1970-01-01
        相关资源
        最近更新 更多