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

发布于 2024-09-30 06:26:32 字数 503 浏览 5 评论 0原文

正如此处所讨论的,函数定义可以在定义之前使用。但一旦一段代码被包装在 try 块中,这种情况就不再是这样了。

这显示“Hello world”:

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

但这显示“ReferenceError:hello is not Define”:

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

因此,相对于函数声明而言,try 块显然有一些“特殊”之处。有什么办法可以绕过这种行为吗?

As discussed here, function definitions can be used before they're defined. But as soon as a section of code is wrapped in a try block, this ceases to be the case.

This displays "Hello world":

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

But this displays "ReferenceError: hello is not defined":

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

So there is clearly something "special" about a try block with respect to function declarations. Is there any way to get around this behavior?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

煮茶煮酒煮时光 2024-10-07 06:26:33

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

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

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

由于声明提升,函数 test 应始终警告“失败”,但在 Firefox 中则不然。上面的代码实际上在 Firefox 中发出“YAY”警报,我怀疑导致这种情况发生的代码最终完全破坏了声明提升。

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

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

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

生产 SourceElement :
语句针对函数进行处理
不采取任何行动的声明。
生产 SourceElement : 声明
评估如下:

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

FunctionDeclaration 和 Statement 都是 SourceElements,因此,语句内不应该有 FunctionDeclarations(if/else、try/catch)。给 Šime Vidas 一块布朗尼!

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

Firefox interprets function statements differently and apparently they broke declaration hoisting for the function declaration. ( A good read about named functions / declaration vs expression )

Why does Firefox interpret statements differently is because of the following code:

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

Due to declaration hoisting, function test should always alert "fail", but not in Firefox. The above code actually alerts "YAY" in Firefox and I suspect the code that makes that happen finally broke declaration hoisting altogether.

I assume Firefox turns function declarations into var declarations when they are located in if/else or try/catch statements. Like so:

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

After a brief debate with Šime Vidas, I have to say that Firefox's dealing with function declarations is non-standard, because of:

The production SourceElement :
Statement is processed for function
declarations by taking no action.
The production SourceElement : Statement
is evaluated as follows:

  1. Evaluate Statement.
  2. Return Result(1).

Both FunctionDeclaration and Statement are SourceElements, ergo, there should be no FunctionDeclarations inside a statement (if/else, try/catch). Give Šime Vidas a brownie!

Try/catch is basically another form of if/else and probably uses the same exception code.

守不住的情 2024-10-07 06:26:33

鉴于函数块通过前向函数引用建立了本地作用域,将 try 块的内容包装在立即函数中似乎可以恢复该行为。

这适用于 Firefox、IE、Chrome:

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

当然,在 try 函数中定义的函数和变量在 catch 块中不再可见,因为它们在没有直接函数包装器的情况下是可见的。但这是 try/catch 脚本包装的一个可能的解决方法。

Given that a function block establishes a local scope with forward function referencing, wrapping the contents of the try block in an immediate function seems to restore that behavior.

This works in Firefox, IE, Chrome:

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

Of course functions and variables defined within the try-function are no longer visible in the catch block, as they would be without the immediate function wrapper. But this is a possible workaround for try/catch script wrapping.

水染的天色ゝ 2024-10-07 06:26:33

您始终可以这样做,并获得两全其美的效果:

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 之外。您还会在函数定义内部的任何垃圾上得到异常。

我想这是一种风格偏好,但对我来说,它似乎比其他选项更具可读性和可维护性。

You can always do it this way and get the best of both worlds:

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

try {
  hello();
}
catch (err) {
  alert(err);
}

You will still get your exceptions in the catch block, but the function will be available. It should be easier to maintain as well, and there is no functional benefit to hoisting functions anyway.

Edit:

To demonstrate that this is just as durable as enveloping the entire code in a try catch, I'm providing a more detailed example.

function hello(str) {
  alert("Hello, " + str);
}

function greet() {
  asdf
}

try {
  var user = "Bob";
  hello(user);
  greet();
  asdf
}
catch (e) {
  alert(e);
}

This will work as expected, no parsing issues. The only locations where it could fail at load time are outside of the function defs and the try catch. You will also get exceptions on any garbage inside of the function defs.

I guess it's a style preference, but it seems to be more readable and maintainable to me than other options.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文