try catch finally 子句中结合 return 会有怎样的效果?
try catch finally 子句是 ECMA2015 - try catch statment 中定义的语法。 其执行机制如下
try {Block} catch 语句
- Let B be the result of evaluating Block.
- If B.[[type]] is throw, then Let C be CatchClauseEvaluation of Catch with parameter B.[[value]].
- Else B.[[type]] is not throw, Let C be B.
- If C.[[type]] is return, or C.[[type]] is throw, return Completion(C).
- If C.[[value]] is not empty, return Completion(C).
- Return Completion{[[type]]: C.[[type]], [[value]]: undefined, [[target]]: C.[[target]]}.
try catch 语句首先会执行try包裹的代码块,根据代码块执行结果判断是否进入catch的代码块,如果catch的代码块有返回结果,则抛出异常时会覆盖try语句的执行结果。否则因为Block是异常抛出,返回undefined。
function test (){
try {
return 0
} catch (e) {
return 1
}
}
test() // 0
function test1 (){
try {
throw new Error()
return 0 // 这里不会执行到
} catch (e) {
return 1
}
}
test1() //1
try {Block} finally 语句
- Let B be the result of evaluating Block.
- Let F be the result of evaluating Finally.
- If F.[[type]] is normal, let F be B.
- If F.[[type]] is return, or F.[[type]] is throw, return Completion(F).
- If F.[[value]] is not empty, return Completion(F).
- Return Completion{[[type]]: F.[[type]], [[value]]: undefined, [[target]]: F.[[target]]}.
Block 和 finally包裹的代码会依次执行,同时记录其返回结果 B 与 F,如果F 有返回值(正常或者异常返回),则返回F的结果,否则返回B的结果
function test (){
try {
throw new Error()
} finally {
return 1
}
}
test() // 1
function test1 (){
try {
throw new Error()
} finally {
throw new Error();
}
}
test1() // Uncaught Error
function test2 (){
try {
return 0
} finally {
}
}
test2() // 0
function test3 (){
try {
return 0
} finally {
return 1
}
}
test3() // 1
try {Block} catch finally 语句
- Let B be the result of evaluating Block.
- If B.[[type]] is throw, thenLet C be CatchClauseEvaluation of Catch with parameter B.[[value]].
- Else B.[[type]] is not throw, let C be B.
- Let F be the result of evaluating Finally.
- If F.[[type]] is normal, let F be C.
- If F.[[type]] is return, or F.[[type]] is throw, return Completion(F).
- If F.[[value]] is not empty, return NormalCompletion(F.[[value]]).
- Return Completion{[[type]]: F.[[type]], [[value]]: undefined, [[target]]: F.[[target]]}.
相当于 try catch 和try finally 的组合执行,先执行try catch 的处理结果 再将其结果与finally合并。
一些有意思的案例
function test() {
var a = 1;
try {
return a;
} finally {
++a;
}
}
test() // 1
function test1() {
var a = 1;
try {
return a;
} finally {
++a;
return a;
}
}
test1() // 2
function test2() {
var obj = {a:1};
try {
return obj;
} finally {
++obj.a;
}
}
test2().a // 2
function test3() {
var obj = {a:1};
try {
return obj.a;
} finally {
++obj.a;
}
}
test1() // 1