正如所讨论的here,函数定义可以在定义之前使用。但是只要一段代码被包装在try块中,就不会出现这种情况了。
显示“Hello world”:
hello();
function hello() { alert("Hello world"); }
但显示“ReferenceError:hello未定义”:
try {
hello();
function hello() { alert("Hello world"); }
} catch (err) {
alert(err);
}
因此,关于函数声明的try块显然有一些“特殊”。有没有办法绕过这种行为?
答案 0 :(得分:26)
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中。上面的代码实际上警告了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")}
}
在与ŠimeVidas进行简短辩论之后,我不得不说Firefox处理函数声明是非标准的,因为:
生产SourceElement: 语句处理功能 声明不采取任何行动 生产SourceElement:Statement 评估如下:
- 评估声明。
- 返回结果(1)。
醇>
FunctionDeclaration和Statement都是SourceElements,ergo,语句中应该没有FunctionDeclarations(if / else,try / catch)。给ŠimeVidas一个布朗尼!
try / catch基本上是if / else的另一种形式,可能使用相同的异常代码。
答案 1 :(得分:5)
假设一个功能块使用正向函数引用建立一个本地作用域,则将try块的内容包装在一个立即函数中似乎可以恢复该行为。
适用于Firefox,IE,Chrome:
try {
(function(){
hello();
function hello() { alert("Hello world"); }
}())
} catch (err) {
alert(err);
}
当然,try-function中定义的函数和变量在catch块中不再可见,因为它们没有立即的函数包装器。但这是try / catch脚本包装的可能解决方法。
答案 2 :(得分:1)
你总是可以这样做,并充分利用这两个方面:
function hello() {
alert("Hello world");
}
try {
hello();
}
catch (err) {
alert(err);
}
您仍会在catch块中获得异常,但该函数将可用。它也应该更容易维护,无论如何都不能提升功能。
修改强>
为了证明这与在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之外。您还将获得函数defs内的任何垃圾的例外。
我想这是一种风格偏好,但它似乎比其他选项更具可读性和可维护性。