这篇文章想跟大家一起从新复习一下对于应用 try...catch
进行异样捕捉的一些知识点。为了晋升大家的浏览趣味,咱们先来做三个小练习题,如果你都做对的话,那么表明你这一部分的常识把握的很纯熟,能够不必读这篇文章啦~ 如果做错了某道题的话,阐明咱们还有一些知识点须要再次坚固一下,话不多说,咱们先来看看这三道题:
function doTask () {
try {console.log('1 in try block');
throw '2 test error';
return 3;
} catch (e) {console.log('4 in catch block');
console.log(e);
return 5;
} finally {console.log('6 in finally block');
return 7;
}
}
// 控制台输入的后果是什么呢?console.log(doTask());
function doWork () {
try {console.log(1);
try {console.log(2);
throw 3;
} finally {console.log(4);
}
console.log(5);
} catch (e) {console.log(e);
}
}
// 控制台输入的后果是什么呢?doWork();
function doRepeat () {for (let i = 0; i < 2; i++) {
try {if (i === 1) {continue;}
console.log(`${i} in try`);
} finally {console.log(`${i} in finally`);
}
}
}
// 控制台的输入后果是什么呢?doRepeat();
下面的每一道题目都有它的小心理,一不小心就容易出错。大家能够把本人测试的后果在评论区晒一晒。
如果你做错了某道题,没有关系,通过这篇文章咱们一起再来温习一下相干的知识点。看到就是学到,让咱们开始吧。
try/catch/finally 的各种模式
try…catch
这种模式应该是咱们在开发中最常常应用的模式了,当咱们须要执行一些可能会抛出谬误的办法或者语句的时候,就会应用 try
将要执行的语句包裹起来,而后紧跟着 catch
去捕捉对应的异样。模式大略如下所示:
try {
// 有概率抛出异样的操作
someErrorProneFn();} catch (e) {
// 打印并且上报接日志
logAndReportError(e);
}
咱们也能够判断 e
的类型,进而依据不同的谬误类型进行不同的操作。
还有一点须要留神的是,catch
也是能够不接管异样信息的。如下所示:
try {
// 有概率抛出异样的操作
someErrorProneFn();} catch {
// 不论下面的操作呈现了什么问题,都间接告诉用户
remindUser();}
这种模式大家在平时开发中用的比拟多,所以用起来是没有什么大问题的。
try…finally
try {connectChannel();
doSomething();} finally {
// 最初做一些清理的工作
cleanup();}
第二种模式就是 try...finally
,这种模式预计大家平时用的比拟少;这种模式个别用于执行一个操作,个别状况下这个操作可能是占用内存比拟高,或者是操作完须要进行内存回收或者敞开连贯或者是敞开数据库之类的。然而咱们可能不是很关注操作过程中呈现的异样。那么咱们就能够在操作实现的时候,进行一些尾部的解决工作。
以后 try
代码块外面的异样还是会抛出到内部的,须要内部进行捕捉和解决。这一点知识点跟下面的第二、第三题有一些关联,咱们稍后会具体跟大家解说一下。
try…catch…finally
这种模式是异样捕捉最全的一种模式,咱们通过 try
代码块执行容易出错的代码,通过 catch
代码块捕捉异样,依据异样的类型别离进行不同的解决;通过 finally
代码块执行最初的操作,个别用来做一些清理的工作。
try...catch...finally
咱们以这种最全的模式作为示例,来解说几个外围的知识点。
try
代码块的执行是最先执行,只有当try
代码块抛出了异样,才会进入catch
代码块。try...finally
中,如果try
代码块中抛出了异样,那么这个异样会被外层最近的catch
代码块捕捉。finally
代码块总是会执行的,不论try
代码块是否抛出异样,以及catch
代码块是否执行。finally
代码块的执行机会:如果try
/catch
代码块中蕴含流程管制语句(例如:return
,break
,continue
,throw
),那么finally
代码块会在这些流程管制语句执行之前执行。如果不蕴含流程管制语句,则在对应的代码块执行实现之后开始执行。如果finally
代码块蕴含流程管制语句,那么finally
代码块的流程管制语句就会先执行,进而替换掉原来try
/catch
中的流程管制语句。这个须要留神。
如果下面的文字描述对你来说还是有点不好了解,那么咱们能够看上面这个我制作的流程图,心愿能够增强你对这一块常识的了解。
下面这些知识点很重要,如果你晓得下面这些知识点的话,那么下面那三道题对你来说是很容易的事件啦。咱们来具体解说一下下面的三道题目。
第 1 道题目
- 首先运行
doTask
函数,进入try
block,打印1 in try block
;而后执行throw '2 test error'
,前面的return 3
不会再执行,所以try
block 就只打印了1 in try block
。 - 因为
try
block 抛出了异样,所以会进入catch
block,而后打印4 in catch block
,接着打印e
,也就是2 test error
,接着筹备开始执行return 5
,因为return 5
是流程管制语句,所以接下来开始执行前面的finally
block。 - 接着打印
6 in finally block
,又因为这个finally
block 含有流程管制语句,所以会替换掉catch
外面的return 5
。 - 最初打印
doTask
函数的返回值:7
所以最终的运算输入的后果是:
1 in try block
4 in catch block
2 test error
6 in finally block
7
第 2 道题目
- 运行
doWork
函数,进入try
block,开始打印:1
; - 进入外部的
try
block,打印:2
;开始执行throw 3
之前,因为throw 3
是流程管制语句,所以首先运行finally
block 外面的语句,打印:4
; - 而后开始执行
throw 3
,前面的console.log(5)
执行不到,间接跳过。异样被最近的外层catch
捕捉,打印:3
。
所以最终的运算输入后果是:
1
2
4
3
第 3 道题目
- 运行函数
doRepeat
,进入第一次循环,i
的值为 0;第一次循环try
/finally
block 都执行,所以先打印:0 in try
,而后打印:0 in finally
; - 第二次循环,
try
block 中遇到了continue
,因为continue
是流程管制语句,所以接下来先执行finally
block 的语句,打印:1 in finally
;而后执行continue
,循环完结。
所以最终的运算输入后果是:
0 in try
0 in finally
1 in finally
前端的好厚米,对于 try/catch/finally
的内容到这里就完结啦,如果你有什么倡议和意见欢送在文章上面评论和留言;如果这篇文章你感觉对你有帮忙,那就帮忙点赞转发一下,咱们下次再见。
参考链接:
- Exception handling statements
- try…catch