再問你一遍,你真的瞭解try..catch(finally)嗎???
定義
首先來看下 MDN 的定義:
The try...catch statement marks a block of statements to try and specifies a response should an exception be thrown.
try...catch語句標記要執行的語句,並指定一個當有異常丟擲時候的響應
簡短的一句的確描述了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,看看會發生什麼。
case1
輸入
function fn() { try { console.log('try塊內log'); } catch (error) { console.log('catch塊內log'); } finally { console.log('finally塊內log===='); } return '一般情況下的return'; } console.log(fn());
輸出:
一切看起來都如我們所想,沒有問題,繼續往下看。
case2
輸入
function fn() { try { console.log('try塊內log'); return 'try中的return'; // <=== 多了這麼一句 } catch (error) { console.log('catch塊內log'); return 'catch中的return語句'; } finally { console.log('finally塊內log===='); } return '一般情況下的return'; } console.log(fn());
輸出
正如上圖所示,這裡列印的是try的return,但是,finally語句塊中的log依然被執行了。
看到這裡,我們可以知道,finally的執行時機是在try(或者cache,cache同理)執行return之前被執行。
那我們就可以驗證下MDN上所說的:finally語句塊的返回值
這句話的真正含義。
case3
輸入
function fn() {
try {
console.log('try塊內log');
return 'try中的return'
} catch (error) {
console.log('catch塊內log');
return 'catch中的return語句';
} finally {
console.log('finally塊內log====');
return 'finaly中的return'; // <=== 多了這麼一句
}
return '一般情況下的return';
}
console.log(fn());
輸出
ok,依然很正常,因為finally會在try的return之前執行,所以攔截了try中的return,列印了finally中的return
。
你以為這樣就結束了嗎?
我們繼續往下看。
case4
輸入
function justLog(){
console.log('來自justLog的列印');
return '來自justLog的return'
}
function fn() {
try {
console.log('try塊內log');
return justLog(); // <=== 這次我們return了一個函式
} catch (error) {
console.log('catch塊內log');
return 'catch中的return語句';
} finally {
console.log('finally塊內log====');
return 'finaly中的return';
}
return '一般情況下的return';
}
console.log(fn());
先思考一下會列印什麼?看看是否和真實的輸出一致。給我們幾秒鐘...
----
----
----
小小的聲援一下,希望戰'役'早日勝利。加油!
然後:
我會長期更新有趣的,有料的前端知識,如果對你有幫忙,請關注我,日後接受第一手更新訊息。非常感謝
----
----
----
輸出
你答對了沒有?
可以看到,紅框內為justLog函式的log,紅框下面是finally中的列印和返回。
所以finally真正的執行時機是:try(或catch)中 return關鍵字之前。
所以我們才看到了justLog中的列印。
有關return關鍵字的實現,可以自行查詢標準,這裡不贅述。
應用場景
比如我們有這樣一個高階函式:
function hoc(fn) {
return fn()
}
我們想要返回所傳遞引數的執行結果,這樣做是沒問題的。
那如果我們想在函式執行之後,return之前,做一些其他操作,應該怎麼做呢?
function hoc(fn) {
const res = fn();
// 其他操作
return res;
}
很簡答,我們可以先獲取返回值,再進行其他操作,然後return。
不過這樣我們就佔用了額外的空間,而且無法便利的複用return後的語句,這個時候,我們的try...catch就可以排上用場了:
function hoc(fn) {
try {
return fn();
} finally {
// 一些其他操作,這些操作會在 `fn()執行後,return執行前` 被執行
}
}
總結
大白話來講,finally
語句塊會在try(或catch)中的 return
關鍵字之前執行。一圖以概之:
最後,如果有幫到你的地方,歡迎關注、交流。