【你不知道的JS】-- 理解 try...catch...finally 语句
finally 中的代码总是会在 try 之后执行,如果有 catch 的话则在 catch 之后执行。也可以将 finally 中的代码看作一个回调函数,即无论出现仕么情况最后定会被调用。
- try 代码块中没有 return 和 throw 语句时
try 代码块中没有 return 和 throw 语句时,会首先执行 try 中的语句,如果在执行时抛出了错误就会被 catch 捕获并执行 catch 中的代码,最终执行 finally 中的代码。 - try 代码块中有 return 或 throw 语句时
function foo() {
try {
return 42;
}
finally {
console.log( "Hello" );
}
console.log( "never runs" );
}
console.log( foo() );
// Hello
// 42
这里return 42
先执行,并将foo()
函数的返回值设置为42
。然后try
执行完毕,接着执行finally
。最后foo()
函数执行完毕,console.log(..)
显示返回值。
try 中的 throw 也是如此
function foo() {
try {
throw 42;
}
finally {
console.log( "Hello" );
}
console.log( "never runs" );
}
console.log( foo() );
// Hello
// Uncatch Exception: 42
- 如果 finally 中抛出异常( 无论有意还是无意),函数就会在此处终止。如果此前 try 中已经有 return 设置了返回值,则该值会被丢弃。
function foo() {
try {
return 42;
}
finally {
throw "Oops!";
}
console.log( "never runs" );
}
console.log( foo() );
// Uncatch Exception: 0ops !
continue 和 break 等控制语句也是如此:
for (var i=0; i<10; i++) {
try {
continue;
}
finally {
console.log(i);
}
}
// 0 1 2 3 4 5 6 7 8 9
continue
在每次循环之后,会在i++
执行之前执行console.log(i)
,所以结果是 0…9 而非 1…10。
- finally 中的 return 会覆盖 try 和 catch 中 return 的返回值。
function foo() {
try {
return 42;
}
finally {
// 没有返回语句,所以没有覆盖
}
}
function bar() {
try {
return 42;
}
finally {
// 覆盖前面的 return 42
return;
}
}
function baz() {
try {
return 42;
}
finally {
// 覆盖前面的 return 42
return "Hello";
}
}
foo(); // 42
bar(); // undefined
baz(); // Hello