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块的代码可能会抛出三种异常:TypeErrorRangeErrorEvalError。当一个异常抛出时,控制将会进入与其对应的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块中发生另一个异常,则包裹该try.catch的相同外部try块中的任何剩余代码(或在主流中,如果不在外部try块中)将不会得到因为控制立即转移到外部try的catch块(或内部的错误发生器,如果不在try块中)。因此,将退出之前在内部(或外部)中完成的任何常规清理代码将被跳过。然而,如果try块具有finally块,那么finally块代码将首先执行,以允许任何这样的清理,然后另一个try的catch-block(或者错误发生器)将被控制来处理第二例。现在,如果try..catch代码成功,则必须执行该例程清理,那么如果finally块仅在异常之后执行,则同样的清理代码必须在finally块的内部和外部都被复制,因此,没有理由只是一个独立的finally块,而是让它执行,不管是否有例外。

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

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语句在trycatch中。这包括在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);
}

// 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
Living Standard Not part of the current ECMA-262 standard: Multiple catch clauses and conditional clauses (SpiderMonkey extension, JavaScript 1.5).

浏览器兼容

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Basic support Yes Yes Yes6 Yes Yes
Conditional clauses No No Yes No No No
FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidIE mobileOpera AndroidiOS Safari
Basic support Yes Yes Yes Yes Yes Yes Yes
Conditional clauses No No No Yes No No No

相关链接

文档标签和贡献者

 最后编辑者: zhangchen,