代码之家  ›  专栏  ›  技术社区  ›  Chris Noe Paweł Dyda

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

  •  32
  • Chris Noe Paweł Dyda  · 技术社区  · 14 年前

    如前所述 here

    显示“Hello world”:

    hello();
    function hello() { alert("Hello world"); }
    

    但显示“ReferenceError:hello is not defined”:

    try {
      hello();
      function hello() { alert("Hello world"); }
    } catch (err) {
      alert(err);
    }
    

    因此,对于函数声明,try块显然有“特殊”之处。有什么办法避免这种行为吗?

    3 回复  |  直到 8 年前
        1
  •  26
  •   BGerrissen    14 年前

    Firefox对函数语句的解释不同,显然它们破坏了函数声明的声明提升。( A good read about named functions / declaration vs expression

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

    if ( true ) {
        function test(){alert("YAY");}
    } else {
        function test(){alert("FAIL");}
    }
    test(); // should alert FAIL
    

    因申报起重、功能 test 应该总是提醒“失败”,但不是在火狐。上面的代码实际上警告了Firefox中的“YAY”,我怀疑导致这种情况发生的代码最终完全破坏了声明提升。

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

    在与ime Vidas进行了简短的讨论之后,我不得不说Firefox处理函数声明是非标准的,因为:

    生产源元素: 为函数处理语句 声明 不采取行动 .
    production SourceElement:语句 评估如下:

    1. 评价语句。

    FunctionDeclaration和Statement都是SourceElements,因此,语句中不应该有FunctionDeclaration(if/else,try/catch)。给我一个布朗尼!

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

        2
  •  5
  •   Chris Noe Paweł Dyda    14 年前

    假设一个函数块通过前向函数引用建立了一个本地作用域,那么将try块的内容包装到一个即时函数中似乎可以恢复该行为。

    这适用于Firefox、IE、Chrome:

    try {
      (function(){
        hello();
        function hello() { alert("Hello world"); }
      }())
    } catch (err) {
      alert(err);
    }
    

        3
  •  1
  •   sworoc    14 年前

    你总是可以这样做,并得到最好的两个世界:

    function hello() {
      alert("Hello world");
    }
    
    try {
      hello();
    }
    catch (err) {
      alert(err);
    }
    

    编辑:

    为了证明这与将整个代码封装在try-catch中一样持久,我提供了一个更详细的示例。

    function hello(str) {
      alert("Hello, " + str);
    }
    
    function greet() {
      asdf
    }
    
    try {
      var user = "Bob";
      hello(user);
      greet();
      asdf
    }
    catch (e) {
      alert(e);
    }
    

    这将按预期工作,没有解析问题。加载时它可能失败的唯一位置是函数defs和try catch之外。在函数def中的任何垃圾上也会出现异常。