try ... catch

try ... catch 语句由一个 try 块和一个 catch 块或 finally 块(或两者皆有)组成。首先执行 try 块中的代码,如果它抛出异常,则将执行 catch 块中的代码。finally 块中的代码将在控制流退出整个结构之前始终被执行。

try {
    tryStatements
} catch (exceptionVar) {
    catchStatements
} finally {
    finallyStatements
}

try 语句总是以 try 块开始。并且,至少存在 catch 块或 finally 块。也可以同时存在 catch 和 finally 块。这为我们提供了 try 语句的三种形式

try...catch
try...finally
try...catch...finally

与其他结构(如 iffor不同,trycatchfinally 块必须是,而不是单个语句

try doSomething(); // SyntaxError
catch (e) console.log(e);

控制流语句(return、throw、break、continue)在 finally 块中将“覆盖” try 块或 catch 块的任何正常完成值。在此示例中,try 块尝试返回 1,但在返回之前,控制流已转移到 finally 块,因此 finally 块的返回值将被返回

function doIt() {
    try {
        return 1;
    } finally {
        return 2;
    }
}

doIt(); // 返回 2

在 finally 块中使用控制流语句通常不是一个好主意。请只将其用于清理代码

嵌套 try 块

首先,让我们看看下面的代码会发生什么

try {
    try {
        throw new Error("哦豁");
    } finally {
        console.log("finally");
    }
} catch (ex) {
    console.error("外层", ex.message);
}

// 输出:
// “finally”
// “外层” “哦豁”

现在,如果我们已经在内部的 try 块中通过添加 catch 块捕获了异常

try {
    try {
        throw new Error("哦豁");
    } catch (ex) {
        console.error("内层", ex.message);
    } finally {
        console.log("最终");
    }
} catch (ex) {
      console.error("外层", ex.message);
}

// 输出:
// “内层” “哦豁”
// “最终”

现在,让我们重新抛出错误

try {
    try {
        throw new Error("哦豁");
    } catch (ex) {
        console.error("内层", ex.message);
        throw ex;
    } finally {
        console.log("最终");
    }
} catch (ex) {
    console.error("外层", ex.message);
}

// 输出:
// “内层” “哦豁”
// “最终”
// “外层” “哦豁”

任何特定的异常只会被直接包裹它的 catch 块捕获一次,除非该异常被重新抛出。当然,如果在“内部”代码块中触发了任何新的异常(因为 catch 块中的代码可能会执行某些操作并抛出异常),这些异常将由外部的 catch 块捕获

从 finally 块返回

如果 finally 块返回一个值,这个值将成为整个 try-catch-finally 语句的返回值,而不管 try 和 catch 块中的 return 语句。这包括 catch 块中抛出的异常

(() => {
  try {
      try {
          throw new Error("哦豁");
      } catch (ex) {
          console.error("内层", ex.message);
          throw ex;
      } finally {
          console.log("最终");
          return;
      }
  } catch (ex) {
      console.error("外层", ex.message);
  }
})();

// 输出:
// “内层” “哦豁”
// “最终”

外层的“哦豁”不会被抛出,因为 finally 块中的 return 语句将控制流转移到外部。同样的规则也适用于 catch 块中返回的值

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容