【问题标题】:Why does a return in `finally` override `try`?为什么`finally`中的返回会覆盖`try`?
【发布时间】:2011-04-19 18:36:17
【问题描述】:

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

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

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

【问题讨论】:

  • 对于其他人,在 catch 块中执行 return false,而不是 finally。

标签: javascript return try-catch try-catch-finally try-finally


【解决方案1】:

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

(术语可能不太正确。)

【讨论】:

    【解决方案2】:

    据我所知,finally 块 总是 执行,无论您在 try 中是否有 return 语句。因此,你得到了 finally 块中 return 语句返回的值。

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

    【讨论】:

      【解决方案3】:

      为什么你得到错误是你在 finally 块中返回。 finally 块应该始终执行。所以你的return true 更改为return false

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • IE8、Firefox 3.6 和 Chrome 6:都一样 ;)
        【解决方案5】:

        最后 always 执行。这就是它的用途,这意味着它的返回值会在您的情况下使用。

        您需要更改您的代码,使其更像这样:

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

        一般来说,您永远不想在一个函数中有多个 return 语句,原因是这样的。

        【讨论】:

        • 我认为拥有多个退货声明并不总是坏事 - 更多讨论请参见 stackoverflow.com/questions/36707/…。
        • 我也不同意一个退货规则。不过,您永远不应该从 finally 返回(在 C# 中,甚至不允许这样做)。
        • @erikkallen - 这是一个很好的观点。最好在 T-C-F 块之外返回,但示例代码会有点强制:)
        • @Castrohenge - 这不是一个硬性规定,但该线程中的大多数 copunter 示例都非常做作,我看到的唯一有效案例是“保护条款”(本质上是模式检查函数顶部的输入数据并有条件地返回)。这是一个完全有效的案例,但实际上这些回报应该是例外(同样不是硬性的)。
        • 实际上在 IE6 和 IE7 中,由于一个相当严重的浏览器错误,finally 并不总是在所有情况下都执行。具体来说——如果在没有被更高级别的 try-catch 包围的 try-finally 块中引发异常,则 finally 块将不会执行。这是一个测试用例jsfiddle.net/niallsmart/aFjKq。此问题已在 IE8 中修复。
        【解决方案6】:

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

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

        1. 设 B 为 Block 求值的结果。
        2. 令 F 为 finally 求值的结果。
        3. 如果F.type正常,返回B。
        4. 返回 F.

        从第 36 页开始:

        Completion 类型用于解释执行非本地控制转移的语句(break、continue、return 和 throw)的行为。 Completion 类型的值是 (type, value, target) 形式的三元组,其中 type 是 normal、break、continue、@ 之一987654329@,或throw,value 是任何 ECMAScript 语言值或空,target 是任何 ECMAScript 标识符或空。

        很明显return false 会将finally 的完成类型设置为return,这会导致try ... finally 执行4。返回 F.

        【讨论】:

        • 在阅读了对这个问题的各种“基本正确但不知何故模糊且不明确”的答案之后,这个问题实际上是有道理的。关键是在 try+catch(返回或抛出或只是正常流程)结束时“发生”的任何事情在运行 finally 部分时都会被记住,然后只有在没有发生任何事情时才会真正发生终于结束了。
        【解决方案7】:

        这个呢?

        doubleReturn();
        
        function doubleReturn() {
          let sex = 'boy';
        
          try {
            return sex;
        
            console.log('this never gets called...');
          } catch (e) {} finally {
            sex = 'girl'; 
        
            alert(sex);
          }
        }
        

        【讨论】:

          【解决方案8】:

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

          只是想指出,如果你从 finally 返回一些东西,那么它将从函数中返回。但是如果 finally 没有“return”字样 - 它将从 try 块中返回值;

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

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

          【讨论】:

            【解决方案9】:

            从 finally 块返回

            如果finally-block 返回一个值,这个值就变成了返回值 整个try-catch-finally 语句的值,无论任何 try 和 catch-blocks 中的 return 语句

            参考:developer.mozilla.org

            【讨论】:

              【解决方案10】:

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

              原因如下:

              • 下面的示例将使用 Express.js 中的 res.send(),它会创建 HTTP 响应并将其分派。
              • 您的 try 和 finally 块都将执行此函数,如下所示:
              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 值与函数范围相关联。

              恕我直言,最好的选择是永远不要在 finally 块内使用 return。它会使您的代码过于复杂并可能掩盖错误。

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

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

              那么你用finally 做什么呢?

              我只会使用finally 来清理东西。对函数的返回值不重要的任何内容。

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

              【讨论】:

              • 强烈同意这个答案 - 只会补充说,如果您遇到返回行为问​​题,只需将返回放在 finally 块之外!它总是在那里运行,除非你在 try/catch 中返回!我认为最终在 try/catch 行为之外使用另一种语言结构会更好,因为这种奇怪之处,例如 do {/*stuff*/} always {/*clean up*/)
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-04-27
              • 2017-07-20
              • 1970-01-01
              • 2013-05-18
              相关资源
              最近更新 更多