Get to know MDN better
此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。
try...catch 语句由一个 try 块和一个 catch 块或 finally 块(或两者皆有)组成。首先执行 try 块中的代码,如果它抛出异常,则将执行 catch 块中的代码。finally 块中的代码将在控制流退出整个结构之前始终被执行。
要执行的语句。
catchStatementstry 块抛出异常后执行的语句。
exceptionVar 可选可选的标识符或模式,用于保存关联的 catch 块所捕获到的异常。如果 catch 块不使用异常的值,你可以省略 exceptionVar 及其周围的括号。
finallyStatements在控制流退出 try...catch...finally 结构之前执行的语句。这些语句无论是否抛出或捕获异常都会执行。
try 语句总是以 try 块开始。并且,至少存在 catch 块或 finally 块。也可以同时存在 catch 和 finally 块。这为我们提供了 try 语句的三种形式:
与其他结构(如 if 或 for)不同,try、catch 和 finally 块必须是块,而不是单个语句。
catch 块包含指定在 try 块中抛出异常时要执行的语句。如果 try 块(或在 try 块内部调用的函数)中的任何语句抛出异常,则立即转移到 catch 块。如果 try 块中没有抛出异常,则跳过 catch 块。
finally 块总是在控制流退出 try...catch...finally 结构之前执行。它总是执行,无论是否抛出或捕获异常。
你可以嵌套多个 try 语句。如果内部 try 语句没有 catch 块,则使用包裹它的 try 语句的 catch 块。
你可以使用 try 语句来处理 JavaScript 异常。有关 JavaScript 异常的更多信息,请参阅 JavaScript 指南。
当 try 块中抛出异常时,exceptionVar(即 catch (e) 中的 e)保存了异常的值。你可以使用这个绑定获取有关抛出的异常的信息。这个绑定只能在 catch 块的作用域中使用。
它不需要是单个标识符。你可以使用解构模式来一次性为多个标识符赋值。
catch 子句创建的绑定与 catch 块处于同一作用域内,因此 catch 块中声明的变量不能与 catch 子句创建的绑定具有相同的名称。(有一个例外,但它是已弃用的语法。)
异常绑定是可写的。例如,你可能需要规范异常值,以确保它是一个 Error 对象。
如果你不需要异常值,你可以省略异常变量及其周围的括号。
finally 块包含要在 try 和 catch 块之后,但在 try...catch...finally 块之后的语句之前执行的语句。控制流将始终进入 finally 块,其执行可以按以下方式进行:
如果进入了 finally 块的控制流来自 try 或 catch 块中的控制流语句(return、throw、break、continue),则该语句的效果将被延迟,直到 finally 块中执行的最后一条语句之后。例如,如果在 try 块抛出异常,即使没有 catch 块来处理异常,finally 块仍然会执行,并且异常会在 finally 块执行完毕后立即抛出。
但是,这条规则有个例外:如果 finally 块中执行的最后一条语句本身就是一个控制流语句,那么该语句将覆盖之前的控制流语句的效果(没有延迟);有关示例,请参阅从 finally 块返回。在 finally 块中使用控制流语句(return、throw、break、continue)通常不是一个好主意,因为它们可以覆盖之前执行的控制流语句的效果,而这很少是预期行为。大多数情况下,finally 块应该用于执行不修改主要逻辑的清理代码。
当使用 catch 块时,catch 块将在 try 块中抛出异常时被执行。例如,在下面的代码中,控制流将被转移到 catch 块。
catch 块指定了一个标识符(如上例中的 e),它保存了异常的值。这个值只能在 catch 块的作用域内使用。
你可以通过将 try...catch 块与 if...else if...else 结构组合起来,创建“条件 catch 块”。例如:
一个常见的用例是仅捕获(并消除)一小部分预期错误,然后在其他情况下重新抛出错误:
这类似与其他语言中的语法,比如 Java:
首先,让我们看看下面的代码会发生什么:
现在,如果我们已经在内部的 try 块中通过添加 catch 块捕获了异常:
现在,让我们重新抛出错误。
任何特定的异常只会被直接包裹它的 catch 块捕获一次,除非该异常被重新抛出。当然,如果在“内部”代码块中触发了任何新的异常(因为 catch 块中的代码可能会执行某些操作并抛出异常),这些异常将由外部的 catch 块捕获。
以下示例展示了 finally 块的一个用例。代码打开一个文件,然后执行使用该文件的语句;finally 块确保文件在使用后始终关闭,即使抛出了异常。
同样,try 块中任何 return 语句的效果都会在 finally 块结束后才生效,尽管返回值表达式是在进入 finally 块之前计算的。
以下示例说明了 finally 块中的控制流语句的行为。当控制流通过第一个 return 语句退出 try 块时,返回值表达式(order.sort())在进入 finally 块之前被计算,函数计划在 finally 块执行完毕后返回该值。然而,finally 块中的 return 语句会覆盖前一个 return 语句的效果,包括其返回值。
同样的逻辑也适用于其他控制流语句。在这里,函数首先计划抛出值 "catch",但最终返回值 "finally"。
再次强调,不建议在 finally 块中使用控制流语句,因为这可能并非预期效果。
| ECMAScript® 2027 Language Specification # sec-try-statement |
启用 JavaScript 以查看此浏览器兼容性表。