为什么“最终”的收益超过“尝试”?


94

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

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

我期望此函数的输出为true,但实际上是false


对于其他人,请在catch块中执行return false,而不是最后一次。
habibhassani

Answers:


91

最后总是执行。这就是它的用途,这意味着您的情况将使用返回值。

您将需要更改代码,因此更像这样:

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

一般来说,您从不希望一个函数中有多个return语句,这就是为什么。


45
我认为拥有多个return语句并不总是不好的-有关更多讨论,请参见stackoverflow.com/questions/36707/…
Castrohenge

5
我也不同意一个返回规则。但是,您永远不应该从finally返回(在C#中,甚至不允许这样做)。
erikkallen

@erikkallen-很好。最好在TCF块之外返回,但示例代码将被强制:)
annakata 2010年

1
@Castrohenge-这不是一成不变的规则,但是该线程中的大多数copunter示例都是非常人为设计的,我看到的唯一有效情况是“ guard子句”(本质上是检查输入数据的模式)函数并有条件地返回)。那是一个完全正确的案例,但实际上那些回报应该是例外(同样不是一成不变的)。
annakata

1
实际上,由于严重的浏览器错误,在IE6和IE7中最终并不一定总是在所有情况下都可以执行。具体来说,如果在没有被较高级别的try-catch包围的try-finally块中引发了异常,则finally块将不会执行。这是一个测试用例jsfiddle.net/niallsmart/aFjKq。此问题已在IE8中修复。
Niall Smart

43

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

生产TryStatement : try Block Finally评估如下:

  1. 令B为评估Block的结果。
  2. 令F为最终评估的结果。
  3. 如果F.type正常,则返回B。
  4. 返回F。

从第36页起:

完成类型用于解释语句(行为breakcontinuereturnthrow)来实现控制的非局部传输。于完成类型的值的形式为三元组(类型,值,目标),其中是以下之一normalbreakcontinuereturn,或throw是任何ECMAScript语言值或空的,并且目标是任何的ECMAScript标识符或清空。

很明显,return false将设置完成类型最后作为回报,导致try ... finally4.返回˚F


2
在阅读了该问题的各种“基本正确但有些糊涂和不清楚的”答案之后,这个问题才变得有意义。关键点是,在try + catch结束时发生的任何“意外情况”(返回或抛出或只是正常流)在它运行最后部分时都会被记住,然后只有在finally末尾什么都没有发生时才发生。
PreventRage

14

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

(术语可能不太正确。)


3

为什么会出错?是您在finally块中返回的。最后块应该总是执行。所以你return truereturn false

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

3

finally块重写try块返回(比方说)。

只是想指出,如果您从finally返回某项,那么它将从函数中返回。但是如果最后没有“ return”字样,它将返回try块中的值;

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

所以-finally- return重写了-try- 的返回值return


1

据我所知,无论内部是否有语句,该finally始终会执行。因此,您将获得finally块中的语句返回的值。returntryreturn

我在Ubuntu中都使用Firefox 3.6.10和Chrome 6.0.472.63对此进行了测试。此代码在其他浏览器中的行为可能会有所不同。


1

我在这里给出一个略有不同的答案:是的,tryfinally块都被执行,并且finally优先于函数的实际“返回”值。但是,这些返回值并不总是在您的代码中使用。

原因如下:

  • 下面的示例将使用res.send()Express.js,后者将创建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值与功能范围关联。

恕我直言,你最好的选择是从来没有使用return一个内部finally。它将使您的代码过于复杂,并可能掩盖错误。

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

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

那你用finally什么呢?

我只会用它finally来清理东西。对于函数的返回值不重要的任何事情。

如果考虑一下,这可能是有道理的,因为当您依赖之下的代码行时finally,您假设try或中可能有错误catch。但是最后两个是错误处理的实际构建块。只需使用returnin try和即可catch


0

从finally块返回

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

参考:developer.mozilla.org


-2

最后,应该总是在try catch块的末尾运行,以便(按规范)是为什么返回false的原因。请记住,不同的浏览器完全有可能具有不同的实现。


IE8,Firefox 3.6和Chrome 6:都一样;)
bonfo 2010年

-3

那这个呢?

doubleReturn();

function doubleReturn() {
  let sex = 'boy';

  try {
    return sex;

    console.log('this never gets called...');
  } catch (e) {} finally {
    sex = 'girl'; 

    alert(sex);
  }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.