【JS】852- 再學(xué)一遍 try...catch

定義
首先來看下 MDN 的定義:
The try...catch statement marks a block of statements to try and specifies a response should an exception be thrown.
try...catch語句標(biāo)記要執(zhí)行的語句,并指定一個當(dāng)有異常拋出時候的響應(yīng)
簡短的一句的確描述了try...catch的大部分功能。
但是,最MDN的最后,有一段話是這么寫的:
Returning from a finally-block
If the finally-block returns a value, this value becomes the return value of the entire try-catch-finally statement, regardless of any return statements in the try and catch-blocks. This includes exceptions thrown inside of the catch-block:
finally語句塊的返回值
如果
finally語句塊中有返回值,那么這個值將作為整個try...catch語句的返回,無論try語句塊或者catch語句塊中是否有返回,這包括了catch中的異常。
ok,那我們就嘗試加上return,看看會發(fā)生什么。
case1
function?fn()?{
??try?{
????console.log('try塊內(nèi)log');
??}?catch?(error)?{
????console.log('catch塊內(nèi)log');
??}?finally?{
????console.log('finally塊內(nèi)log====');
??}
??return?'一般情況下的return';
}
console.log(fn());

一切看起來都如我們所想,沒有問題,繼續(xù)往下看。
case2
function?fn()?{
??try?{
????console.log('try塊內(nèi)log');
????return?'try中的return';?//?<===?多了這么一句
??}?catch?(error)?{
????console.log('catch塊內(nèi)log');
????return?'catch中的return語句';
??}?finally?{
????console.log('finally塊內(nèi)log====');
??}
??return?'一般情況下的return';
}
console.log(fn());

正如上圖所示,這里打印的是
try的return,但是,finally語句塊中的log依然被執(zhí)行了??吹竭@里,我們可以知道,finally的執(zhí)行時機是在try(或者cache,cache同理)執(zhí)行return之前被執(zhí)行。那我們就可以驗證下MDN上所說的:finally語句塊的返回值 這句話的真正含義。
case3
function?fn()?{
??try?{
????console.log('try塊內(nèi)log');
????return?'try中的return'
??}?catch?(error)?{
????console.log('catch塊內(nèi)log');
????return?'catch中的return語句';
??}?finally?{
????console.log('finally塊內(nèi)log====');
????return?'finaly中的return';?//?<===?多了這么一句
??}
??return?'一般情況下的return';
}
console.log(fn());

ok,依然很正常,因為finally會在try的return之前執(zhí)行,所以攔截了try中的return,打印了finally中的return。
你以為這樣就結(jié)束了嗎?
我們繼續(xù)往下看。
case4
function?justLog(){
??console.log('來自justLog的打印');
??return?'來自justLog的return'
}
function?fn()?{
??try?{
????console.log('try塊內(nèi)log');
????return?justLog();?//?<===?這次我們return了一個函數(shù)
??}?catch?(error)?{
????console.log('catch塊內(nèi)log');
????return?'catch中的return語句';
??}?finally?{
????console.log('finally塊內(nèi)log====');
????return?'finaly中的return';
??}
??return?'一般情況下的return';
}
console.log(fn());
先思考一下會打印什么?看看是否和真實的輸出一致。給我們幾秒鐘...

可以看到,紅框內(nèi)為 justLog函數(shù)的log,紅框下面是finally中的打印和返回。所以 finally真正的執(zhí)行時機是:try(或catch)中return關(guān)鍵字之前。所以我們才看到了 justLog中的打印。有關(guān) return關(guān)鍵字的實現(xiàn),可以自行查詢標(biāo)準(zhǔn),這里不贅述。
應(yīng)用場景
比如我們有這樣一個高階函數(shù):
function?hoc(fn)?{
??return?fn()
}
我們想要返回所傳遞參數(shù)的執(zhí)行結(jié)果,這樣做是沒問題的。
那如果我們想在函數(shù)執(zhí)行之后,
return之前,做一些其他操作,應(yīng)該怎么做呢?
function?hoc(fn)?{
??const?res?=?fn();
??//?其他操作
??return?res;
}
很簡答,我們可以先獲取返回值,再進行其他操作,然后 return。不過這樣我們就占用了額外的空間,而且無法便利的復(fù)用 return后的語句,這個時候,我們的try...catch就可以排上用場了:
function?hoc(fn)?{
??try?{
????return?fn();
??}?finally?{
????//?一些其他操作,這些操作會在?`fn()執(zhí)行后,return執(zhí)行前`?被執(zhí)行
??}
}
總結(jié)
大白話來講,
finally語句塊會在try(或catch)中的return關(guān)鍵字之前執(zhí)行。一圖以概之:


回復(fù)“加群”與大佬們一起交流學(xué)習(xí)~
點擊“閱讀原文”查看 100+ 篇原創(chuàng)文章
