Why can't I use a Javascript function before its definition inside a try block?
如此处所讨论的,函数定义可以在定义之前使用。 但是只要一段代码被包装在try块中,就不再是这种情况了。
这显示"Hello world":
1 2 | hello(); function hello() { alert("Hello world"); } |
但是这会显示"ReferenceError:hello is not defined":
1 2 3 4 5 6 | try { hello(); function hello() { alert("Hello world"); } } catch (err) { alert(err); } |
因此,关于函数声明的try块显然有一些"特殊"。 有没有办法绕过这种行为?
Firefox以不同的方式解释函数语句,显然它们破坏了函数声明的声明提升。 (关于命名函数/声明vs表达的好读物)
为什么Firefox不同地解释语句是因为以下代码:
1 2 3 4 5 6 | if ( true ) { function test(){alert("YAY");} } else { function test(){alert("FAIL");} } test(); // should alert FAIL |
由于声明提升,函数
我假设Firefox将函数声明转换为var声明,当它们位于if / else或try / catch语句中时。像这样:
1 2 3 4 5 6 7 | // firefox interpretted code var test; // hoisted if (true) { test = function(){alert("yay")} } else { test = function(){alert("fail")} } |
在与ime Vidas进行简短的辩论之后,我不得不说Firefox处理函数声明是非标准的,因为:
The production SourceElement :
Statement is processed for function
declarations by taking no action.
The production SourceElement : Statement
is evaluated as follows:Evaluate Statement. Return Result(1).
函数声明和声明都是SourceElements,因此,声明中应该没有FunctionDeclarations(if / else,try / catch)。给我?维达斯一个布朗尼!
Try / catch基本上是if / else的另一种形式,可能使用相同的异常代码。
假定函数块使用正向函数引用建立本地作用域,则将try块的内容包装在立即函数中似乎可以恢复该行为。
这适用于Firefox,IE,Chrome:
1 2 3 4 5 6 7 8 | try { (function(){ hello(); function hello() { alert("Hello world"); } }()) } catch (err) { alert(err); } |
当然,try-function中定义的函数和变量在catch块中不再可见,因为它们没有立即函数包装器。但这是try / catch脚本包装的可能解决方法。
你总是可以这样做,并充分利用这两个方面:
1 2 3 4 5 6 7 8 9 10 | function hello() { alert("Hello world"); } try { hello(); } catch (err) { alert(err); } |
您仍将在catch块中获取异常,但该函数将可用。它也应该更容易维护,并且无论如何提升功能都没有功能上的好处。
编辑:
为了证明这与在try catch中包含整个代码一样耐用,我提供了一个更详细的例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function hello(str) { alert("Hello," + str); } function greet() { asdf } try { var user ="Bob"; hello(user); greet(); asdf } catch (e) { alert(e); } |
这将按预期工作,没有解析问题。它在加载时可能失败的唯一位置在函数defs和try catch之外。您还将获得函数defs内部任何垃圾的例外情况。
我想这是一种风格偏好,但它似乎比其他选项更具可读性和可维护性。