`try...catch`语句将能引发错误的代码放在try块中，并且对应一个响应，然后有异常被抛出。

## 语法

    try {
       try_statements
    }
    [catch (exception_var_1 if condition_1) { // non-standard
       catch_statements_1
    }]
    ...
    [catch (exception_var_2) {
       catch_statements_2
    }]
    [finally {
       finally_statements
    }]

`try_statements`
  需要被执行的语句。

`catch_statements_1`, `catch_statements_2`
  如果在`try`块里有异常被抛出时执行的语句。

`exception_var_1`, `exception_var_2`
  用于保存关联`catch`子句的异常对象的标识符。

`condition_1`
  一个条件表达式。

`finally_statements`
  在`try`语句块之后执行的语句块。无论是否有异常抛出或捕获这些语句都将执行。

## 描述

`try`语句包含了由一个或者多个语句组成的`try`块, 和至少一个`catch`子句或者一个`finally`子句的其中一个，或者两个兼有， 下面是三种形式的`try`声明：

1. `try...catch`
2. `try...finally`
3. `try...catch...finally`

`catch`子句包含`try`块中抛出异常时要执行的语句。也就是，你想让`try`语句中的内容成功， 如果没成功，你想控制接下来发生的事情，这时你可以在`catch`语句中实现。 如果在`try`块中有任何一个语句（或者从`try`块中调用的函数）抛出异常，控制立即转向`catch`子句。如果在`try`块中没有异常抛出，会跳过`catch`子句。

`finally`子句在`try`块和`catch`块之后执行但是在下一个`try`声明之前执行。无论是否有异常抛出或捕获它总是执行。

你可以嵌套一个或者更多的`try`语句。如果内部的`try`语句没有`catch`子句，那么将会进入包裹它的`try`语句的`catch`子句。

你也可以用`try`语句去处理 JavaScript 异常。参考JavaScript 指南了解更多关于 Javascript 异常的信息。

### 无条件的`catch`子句

当使用单个无条件`catch`子句时，抛出的任何异常时都会进入到`catch`块。例如，当在下面的代码中发生异常时，控制转移到`catch`子句。

    try {
       throw "myException"; // generates an exception
    }
    catch (e) {
       // statements to handle any exceptions
       logMyErrors(e); // pass exception object to error handler
    }

`catch`块指定一个标识符（在上面的示例中为e），该标识符保存由`throw`语句指定的值。`catch`块是唯一的，因为当输入`catch`块时，JavaScript 会创建此标识符，并将其添加到当前作用域；标识符仅在`catch`块执行时存在；`catch`块执行完成后，标识符不再可用。

### 条件`catch`子句

非标准
该特性是非标准的，请尽量不要在生产环境中使用它！

你也可以用一个或者更多条件`catch`子句来处理特定的异常。在这种情况下，当异常抛出时将会进入合适的`catch`子句中。在下面的代码中，`try`块的代码可能会抛出三种异常：`TypeError`，`RangeError`和`EvalError`。当一个异常抛出时，控制将会进入与其对应的`catch`语句。如果这个异常不是特定的，那么控制将转移到无条件`catch`子句。

当用一个无条件`catch`子句和一个或多个条件语句时，无条件`catch`子句必须放在最后。否则当到达条件语句之前所有的异常将会被非条件语句拦截。

提醒：这个功能不符合 ECMAscript 规范。

    try {
        myroutine(); // may throw three types of exceptions
    } catch (e if e instanceof TypeError) {
        // statements to handle TypeError exceptions
    } catch (e if e instanceof RangeError) {
        // statements to handle RangeError exceptions
    } catch (e if e instanceof EvalError) {
        // statements to handle EvalError exceptions
    } catch (e) {
        // statements to handle any unspecified exceptions
        logMyErrors(e); // pass exception object to error handler
    }

下面用符合 ECMAscript 规范的简单的 JavaScript 来编写相同的“条件catch子句”（显然更加冗长的，但是可以在任何地方运行）：

    try {
        myroutine(); // may throw three types of exceptions
    } catch (e) {
        if (e instanceof TypeError) {
            // statements to handle TypeError exceptions
        } else if (e instanceof RangeError) {
            // statements to handle RangeError exceptions
        } else if (e instanceof EvalError) {
            // statements to handle EvalError exceptions
        } else {
           // statements to handle any unspecified exceptions
           logMyErrors(e); // pass exception object to error handler
        }
    }

### 异常标识符

当`try`块中的抛出一个异常时， `exception_var`（如`catch (e)`中的`e`）用来保存被抛出声明指定的值。你可以用这个标识符来获取关于被抛出异常的信息。

这个标识符是`catch`子语句内部的。换言之，当进入`catch`子语句时标识符创建，`catch`子语句执行完毕后，这个标识符将不再可用。

### `finally`子句

`finally`子句包含的语句，是在`try`块和`catch`子句之后，但在`try..catch..finally`块之后的语句之前执行。请注意，无论是否抛出异常`finally`子句都会执行。此外，如果抛出异常，即使没有`catch`子句处理异常，`finally`子句中的语句也会执行。

当发生异常时，可以使用`finally`子句使您的脚本以更优雅的方式失败；例如，进行通常的清理，您可能需要释放脚本已经绑定的资源。

不管是否有异常发生，一个特殊异常相关的子句总会执行，这看起来可能有些奇怪，但这种结构确实是有用的。但重点不是`finally`子句总是会执行，而是`try..catch`语句后面的其它普通代码不会执行。

例如，如果`try`的`catch-block`中发生另一个异常，则包裹该`try..catch`的外部`try-block`中的剩余代码（或在主流中，如果不在外部`try-block`中）将不会执行，因为控制流会立即跳转到外部`try`的`catch-block`（或内部的错误发生器，如果不在`try-block`中）。

因此，外部的包裹`try-block`（或主流）退出之前完成常规清理的代码将被跳过。然而，如果`try-block`有一个`finally-block`，那么`finally-block`代码将可以先来执行这些清理，然后另一个try的`catch-block`（或者错误发生器）再来处理第二个异常。

现在，如果无论`try..catch`代码执行成功与否，清理例程都必须执行，并且`finally-block`只在发生异常时才执行，那么`finally-block`内部和外部需要多复制一份同样的清理例程，所以没有理由不只保留一个`finally-block`，并且不管是否有异常，都让它执行。

以下示例打开一个文件，然后执行使用该文件的语句（服务器端 JavaScript 允许您访问文件）。如果文件打开时抛出异常，则`finally`子句会在脚本失败之前关闭该文件。finally中的代码最终也会在`try`或`catch block`显式返回时执行。

    openMyFile()
    try {
       // tie up a resource
       writeMyFile(theData);
    }
    finally {
       closeMyFile(); // always close the resource
    }

## 示例

### 嵌套 try 块

首先让我们看看这里发生什么：

    try {
      try {
        throw new Error("oops");
      }
      finally {
        console.log("finally");
      }
    }
    catch (ex) {
      console.error("outer", ex.message);
    }

    // Output:
    // "finally"
    // "outer" "oops"

现在，如果我们已经捕获异常通过增加一个 catch 语句块

    try {
      try {
        throw new Error("oops");
      }
      catch (ex) {
        console.error("inner", ex.message);
      }
      finally {
        console.log("finally");
      }
    }
    catch (ex) {
      console.error("outer", ex.message);
    }

    // Output:
    // "inner" "oops"
    // "finally"

现在，让我们再次抛出错误。

    try {
      try {
        throw new Error("oops");
      }
      catch (ex) {
        console.error("inner", ex.message);
        throw ex;
      }
      finally {
        console.log("finally");
      }
    }
    catch (ex) {
      console.error("outer", ex.message);
    }

    // Output:
    // "inner" "oops"
    // "finally"
    // "outer" "oops"

任何给定的异常只会被离它最近的封闭 catch 块捕获一次。当然，在“inner”块抛出的任何新异常 （因为 catch 块里的代码也可以抛出异常），将会被“outer”块所捕获。

### 从 finally 语句块返回

如果从`finally`块中返回一个值，那么这个值将会成为整个`try-catch-finally`的返回值，无论是否有`return`语句在`try`和`catch`中。这包括在`catch`块里抛出的异常。

    try {
      try {
        throw new Error("oops");
      }
      catch (ex) {
        console.error("inner", ex.message);
        throw ex;
      }
      finally {
        console.log("finally");
        return;
      }
    }
    catch (ex) {
      console.error("outer", ex.message);
    }

    // 注: 此 try catch 语句需要在 function 中运行才能作为函数的返回值, 否则直接运行会报语法错误
    // Output:
    // "inner" "oops"
    // "finally"

因为 finally 块里的 return 语句，"oops" 没有抛出到外层, 从 catch 块返回的值同样适用。

## 规范

Specification | Status | Comment
--- | --- | ---
ECMAScript 3rd Edition (ECMA-262) | Standard | Initial definition. Implemented in JavaScript 1.4
ECMAScript 5.1 (ECMA-262) try statement | Standard |
ECMAScript 2015 (6th Edition, ECMA-262) try statement | Standard |
ECMAScript Latest Draft (ECMA-262) try statement | Draft | Not part of the current ECMA-262 standard: Multiple catch clauses and conditional clauses (SpiderMonkey extension, JavaScript 1.5).

## 浏览器兼容

The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.

Update compatibility data on GitHub

| Desktop | Mobile | Server
| Chrome | Edge | Firefox | Internet Explorer | Opera | Safari | Android webview | Chrome for Android | Edge Mobile | Firefox for Android | Opera for Android | Safari on iOS | Samsung Internet | Node.js
`try...catch` | Chrome Full support Yes | Edge Full support Yes | Firefox Full support 1 | IE Full support 6 | Opera Full support Yes | Safari Full support Yes | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile Full support Yes | Firefox Android Full support 4 | Opera Android Full support Yes | Safari iOS Full support Yes | Samsung Internet Android Full support Yes | nodejs Full support Yes
Conditional clauses Deprecated Non-standard | Chrome No support No | Edge No support No | Firefox No support 1 — 59 | IE No support No | Opera No support No | Safari No support No | WebView Android No support No | Chrome Android No support No | Edge Mobile No support No | Firefox Android No support 4 — 59 | Opera Android No support No | Safari iOS No support No | Samsung Internet Android No support No | nodejs No support No
Optional catch binding | Chrome Full support 66 | Edge No support No | Firefox Full support 58 | IE No support No | Opera Full support 53 | Safari No support No | WebView Android Full support 66 | Chrome Android Full support 66 | Edge Mobile No support No | Firefox Android Full support 58 | Opera Android Full support 53 | Safari iOS No support No | Samsung Internet Android No support No | nodejs No support No

### Legend

Full support
  Full support
No support
  No support
Non-standard. Expect poor cross-browser support.
  Non-standard. Expect poor cross-browser support.
Deprecated. Not for use in new websites.
  Deprecated. Not for use in new websites.

## 相关链接

- `Error`
- `throw`