为什么我不能在try块中定义之前使用Javascript函数?

Chr*_*Noe 32 javascript firefox function try-catch forward-declaration

作为讨论在这里,在定义前,他们可以用函数定义.但是只要一段代码被包装在try块中,就不再是这种情况了.

这显示"Hello world":

hello();
function hello() { alert("Hello world"); }
Run Code Online (Sandbox Code Playgroud)

但是这会显示"ReferenceError:hello is not defined":

try {
  hello();
  function hello() { alert("Hello world"); }
} catch (err) {
  alert(err);
}
Run Code Online (Sandbox Code Playgroud)

因此,关于函数声明的try块显然有一些"特殊".有没有办法绕过这种行为?

BGe*_*sen 26

Firefox以不同的方式解释函数语句,显然它们破坏了函数声明的声明提升.(关于命名函数/声明vs表达的好读物)

为什么Firefox不同地解释语句是因为以下代码:

if ( true ) {
    function test(){alert("YAY");}
} else {
    function test(){alert("FAIL");}
}
test(); // should alert FAIL
Run Code Online (Sandbox Code Playgroud)

由于声明提升,功能test应始终警告"失败",但不是在Firefox中.上面的代码实际上警告了Firefox中的"YAY",我怀疑使这种情况发生的代码最终完全破坏了声明吊装.

我假设Firefox将函数声明转换为var声明,当它们位于if/else或try/catch语句中时.像这样:

// firefox interpretted code
var test; // hoisted
if (true) {
   test = function(){alert("yay")}
} else {
   test = function(){alert("fail")}
}
Run Code Online (Sandbox Code Playgroud)

在与ŠimeVidas进行简短辩论后,我不得不说Firefox处理函数声明是非标准的,因为:

生成的SourceElement:Statement 通过不执行任何操作来处理函数声明.
生产SourceElement:Statement的计算方法如下:

  1. 评估声明.
  2. 返回结果(1).

函数声明和声明都是SourceElements,因此,声明中应该没有FunctionDeclarations(if/else,try/catch).给ŠimeVidas一个布朗尼!

Try/catch基本上是if/else的另一种形式,可能使用相同的异常代码.

  • @BGerrissen您可以使用上面评论中提供的相同链接.首先,向下滚动到第14章,其中声明程序是语句和函数声明的列表.然后,向上滚动到第12章.在那里,您可以检查`Statement`生成.在这里,您可以看到有哪些语句以及它们的语法.您可能必须浏览整个章节(12),但您将看到不允许任何语句包含`FunctionDeclaration`生产(表示函数声明). (2认同)

Chr*_*Noe 5

假定函数块使用正向函数引用建立本地作用域,则将try块的内容包装在立即函数中似乎可以恢复该行为.

这适用于Firefox,IE,Chrome:

try {
  (function(){
    hello();
    function hello() { alert("Hello world"); }
  }())
} catch (err) {
  alert(err);
}
Run Code Online (Sandbox Code Playgroud)

当然,try-function中定义的函数和变量在catch块中不再可见,因为它们没有立即函数包装器.但这是try/catch脚本包装的可能解决方法.