目录
1. 语法
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
语句块之后执行的语句块。无论是否有异常抛出或捕获这些语句都将执行。
2. 详解
try
语句包含了由一个或者多个语句组成的try
块, 和至少一个catch
块或者一个finally
块的其中一个,或者两个兼有, 下面是三种形式的try
声明:
try...catch
try...finally
try...catch...finally
catch
子句包含try
块中抛出异常时要执行的语句。也就是,你想让try
语句中的内容成功, 如果没成功,你想控制接下来发生的事情,这时你可以在catch
语句中实现。 如果在try
块中有任何一个语句(或者从try
块中调用的函数)抛出异常,控制立即转向catch
子句。如果在try
块中没有异常抛出,会跳过catch
子句。
finally
子句在try
块和catch
块之后执行但是在下一个try
声明之前执行。无论是否有异常抛出或捕获它总是执行。
你可以嵌套一个或者更多的try
语句。如果内部的try
语句没有catch
子句,那么将会进入包裹它的try
语句的catch
子句。
3. 无条件的catch
块
所谓无条件catch块就是单个子句的try..catch 抛出的异常都会被catch捕获,例如,当在下面的代码中发生异常时,控制转移到catch
子句。
try {
nonExistentFunction(); // 不存在的函数
} catch (error) {
console.error(error);
// 控制台打印: ReferenceError: nonExistentFunction is not defined
// 被catch捕获错误。
}
打印出来的错误时可以自定义的。catch
块指定一个标识符,该标识符保存由throw
语句指定的值。catch
块是唯一的,因为当输入catch
块时,JavaScript 会创建此标识符,并将其添加到当前作用域;标识符仅在catch
块执行时存在;catch
块执行完成后,标识符不再可用。
try {
throw "自定义一些文字错误"; // generates an exception
}
catch (e) {
console.log(e); // 控制台打印:自定义一些文字错误
}
try {
throw {name: '张三'}; // 自定义
}
catch (e) {
console.log(e); // 打印: {name: '张三'}
}
try
块中的抛出一个异常时, exception_var
(如catch (e)
中的e
)用来保存被抛出声明指定的值。你可以用这个标识符来获取关于被抛出异常的信息。
这个标识符是catch
子语句内部的。换言之,当进入catch
子语句时标识符创建,catch
子语句执行完毕后,这个标识符将不再可用。
4. finally
块
finally
块包含的语句在try
块和catch
之后,try..catch..finally
块后的语句之前执行。请注意,无论是否抛出异常finally
子句都会执行。此外,如果抛出异常,即使没有catch
子句处理异常,finally
子句中的语句也会执行。
openMyFile()
try {
// tie up a resource
writeMyFile(theData);
}
finally {
closeMyFile(); // always close the resource
}
5. 嵌套try
例子1:
try {
try {
throw new Error("oops"); // 抛出oops错误对象
}
finally {
console.log("finally"); // 必须执行的
}
}
catch (ex) {
console.error("outer", ex.message);
}
// 结果:
// "finally"
// "outer" "oops"
例2 如果我们已经在 try 语句中,通过增加一个 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); // 属于这个try catch 没有异常抛出
}
// 结果:
// "inner" "oops"
// "finally"
例3 在新增的catch里不干正事继续抛错误
try {
try {
throw new Error("oops"); // 异常
}
catch (ex) {
console.error("inner", ex.message); // 捕获到异常
throw ex; // 不干正事的抛出异常 但是还是会先执行finally内的内容
}
finally {
console.log("finally"); // try 和 catch 执行完就执行。不管别人
}
}
catch (ex) {
console.error("outer", ex.message); // 捕获到属于这个try -catch 的异常
}
// 结果:
// "inner" "oops"
// "finally"
// "outer" "oops"
例4 特别!!!
function setName () {
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 中运行才能作为函数的返回值, 否则直接运行会报语法错误
// 结果:
// "inner" "oops"
// "finally"
}
如果从
finally
块中返回一个值,那么这个值将会成为整个try-catch-finally
的返回值,无论是否有return
语句在try
和catch
中。这包括在catch
块里抛出的异常。因为 finally 块里的 return 语句,"oops" 没有抛出到外层,从 catch 块返回的值同样适用。