为什么“ finally”中的 return 会覆盖“ try”?

Try/catch 块中的 return 语句是如何工作的?

function example() {
try {
return true;
}
finally {
return false;
}
}

我期望这个函数的输出是 true,但实际上它是 false

62716 次浏览

使用 finally时,该块中的任何代码都会在方法退出之前触发。因为您在 finally块中使用了一个返回值,所以它调用 return false并覆盖 try块中以前的 return true

(术语可能不太对。)

据我所知,无论您在 try中是否有 return语句,finally一直都是都会执行。因此,您将获得 finally 块中的 return语句返回的值。

我在 Ubuntu 中用 Firefox 3.6.10和 Chrome 6.0.472.63测试了这个。这段代码在其他浏览器中的行为可能有所不同。

为什么你会得到假的是你返回了一个 finally 块。Finally 块应该始终执行。所以你的 return true变成了 return false

function example() {
try {
return true;
}
catch {
return false;
}
}

最后应该总是在 try catch 块的末尾运行,这样(根据规范)就会得到错误返回。请记住,不同的浏览器完全有可能有不同的实现。

最后执行 一直都是,这就是它的作用,这意味着它的返回值将在您的情况下使用。

你需要改变你的代码,让它更像这样:

function example() {
var returnState = false; // initialization value is really up to the design
try {
returnState = true;
}
catch {
returnState = false;
}
finally {
return returnState;
}
}

一般来说,一个函数中永远不要有多个 return 语句,这就是原因。

根据 ECMA-262(2009年12月第5版) ,第96页:

TryStatement : try Block Finally的生产情况评估如下:

  1. 设 B 为求块的结果。
  2. 设 F 是最终评估的结果。
  3. 如果 F 类型正常,返回 B。
  4. 回程 F。

第36页:

Completion 类型用于解释执行非本地控制转移的语句(breakcontinuereturnthrow)的行为。Completion 类型的值是形式 (类型、值、目标)的三元组,其中 continue0是 normalbreakcontinuereturnthrow中的一个,continue1是任何 ECMAScript 语言值或空,而 continue2是任何 ECMAScript 标识符或空。

很明显,return false终于的完成类型设置为 返回,这导致 try ... finally4. 返回 F

Finally 块重写 try 块 return (形象地说)。

只是想指出,如果从 finally 返回某个值,那么它将从函数返回。但是如果在最后没有返回字-它将返回的值从 try 块;

function example() {
try {
return true;
}
finally {
console.log('finally')
}
}
console.log(example());
// -> finally
// -> true

因此-finally-return重写-try-return的返回值。

从 finally-block 返回

如果 finally块返回一个值,则该值将成为返回值 整个 try-catch-finally语句的值,而不管任何 trycatch块中的 return语句

参考资料: Developer.mozilla.org

这里我要给出一个稍微不同的答案: 是的,tryfinally块都得到了执行,而且 finally优先于函数的实际“ return”值。但是,这些返回值并不总是在代码中使用。

原因如下:

  • 下面的示例将使用 Express.js 中的 res.send(),它将创建一个 HTTP 响应并分派它。
  • 您的 tryfinally块都将像下面这样执行这个函数:
try {
// Get DB records etc.
return res.send('try');
} catch(e) {
// log errors
} finally {
return res.send('finally');
}

此代码将在浏览器中显示字符串 try。此外,该示例将在控制台中显示一个错误。res.send()函数称为 两次。任何函数都会发生这种情况。Try-catch-finally 块将混淆这个事实,让未经训练的人看不出来,因为(个人而言)我只将 return值与函数范围相关联。

我认为你最好的选择是 不要在 ABC1块中使用 return。它会使你的代码过于复杂并且可能掩盖错误。

事实上,在 PHPStorm 中有一个默认的代码检查规则设置,为此提供了一个“警告”:

Https://www.jetbrains.com/help/phpstorm/javascript-and-typescript-return-inside-finally-block.html

那么 finally的用途是什么呢?

我将使用 finally只清理东西。任何不是关键的返回值的函数。

如果您仔细想想,这可能是有意义的,因为当您依赖于 finally下的一行代码时,您假设 trycatch中可能存在错误。但是最后两个是错误处理的实际构建块。只需在 trycatch中使用 return即可。