try...catch? 為何不用if...else就好了?
相信在開始學寫JS的初期都是if...else條件判斷用爽爽,然後突然有個學姊說可以試試看用try...catch,不會一直巢狀下去,而且還可以統一錯誤處理喔!
接著開始研究try...catch,可是覺得怎麼沒有一篇文章看得懂?太難了吧!
好的,我自首。以上是我剛學try...catch的小劇場 XD
可是在後來把try...catch學起來之後就覺得喔喔喔喔,好方便喔~就可以不用管這塊了耶!
現在看文章的人應該都還不太懂try...catch吧?
我來講講以前我看不懂的細節,讓過去的我看應該看得懂的文章
try...catch 就是有一個try 區塊跟 catch 區塊,如果在try 區塊執行有錯誤或者例外情形的話就跳到catch 區塊去處理。
try {
//要被執行的部分
} carch(error) {
//要攔截錯誤的部分
}
錯誤是什麼意思? 在if...else的朋友,錯誤不是false的意思喔。
false是你們自己定義的false,而錯誤是會報錯的那種錯誤,例如我在try 區塊放了一個根本沒有的變數、函式,正常的node or 瀏覽器都會報錯對吧?但我們如果在try...catch裡面,就可以控制這個錯誤,不要讓他全部報錯。
來看看範例:
呼叫一個根本不知道哪裡來的hello(),他就會報錯,像這樣:
可是如果是在try區塊呼叫一個根本不知道哪裡來的hello()的話,一發現有錯就會直接跳到catch,然後印出錯誤訊息
try {
hello()
} catch(error) {
console.log(error.message)
}
錯誤訊息:
因為我們的錯誤處理就只是讓他console.log()印出東西而已。
但也是可以讓他紅紅的喔,改成console.error()就好了。
那,我可以像是if...else一樣自己定義我要的false嗎?
Of course you can!
接著我們就要講到catch的那個奇妙的參數了
try...catch那個catch為什麼有一個參數啊?
我們來看看MDN上的定義:
The catch-block specifies an identifier (e in the example above) that holds the value of the exception; this value is only available in the scope of the catch-block.
這個參數的值就是一個識別符的意思,你可以自己定義,要e or error as you like。
裡面的 error.message
就是可以去定義要報出什麼錯誤了,像上面我沒有定義,他就跑出「hello is not define」這種我們很常見到的句子,這就是當JS找到沒有被定義的函式會跑出來的錯誤提示。
現在來到正題了,定義錯誤or例外。
throw new Error()就是丟出一個錯誤,先來看個範例我故意在try裡面就throw
可以看到程式根本不會運行到console.log("Hi")
的部分,就到catch裡面了。
要在哪個地方丟錯誤就放throw new Error(),這邊就有點像是 else的部分。
現階段我會用到try...catch的時候是在驗證使用者輸入的數字的時候,會控制輸入的數字一定要是整數,這就是我定義的例外情形(expection)。
會寫一個function來驗證錯誤,裡面會用if判斷,但會用反向的方式去寫。
來看看我寫的驗證錯誤的範例:
意思是如果不是正整數,就丟出 "不是正整數啊!" 的提醒。
function checkIsInteger(number) {
if (!Number.isInteger(number)) {
throw new Error("不是正整數啊!");
}
}
然後在主要的function裡面呼叫他:
function add(number1, number2) {
try {
checkIsInteger(number1);
checkIsInteger(number2);
const result = number1 + number2;
return result;
} catch (error) {
console.log(error.message);
}
}
// 故意傳一個不是正整數的
const result = add(0.5, 1);
console.log(result);
這個add function,要輸入兩個數字,而且都要通過 checkIsInteger的試煉之後才能繼續相加。
再看看驗證函式,裡面的throw new Error(" "),就是丟出一個錯誤物件,這個new Error就是JS提供給錯誤處理使用的。
意思是,在這裡符合 if 條件的時候創建了一個Error物件,參數「不是正整數」就帶進去變成錯誤物件的message。
function checkIsInteger(number) {
if (!Number.isInteger(number)) {
throw new Error("不是正整數啊!");
}
}
所以這裡可以連到catch的 error.message,這時候我已經把這個function的錯誤物件準備好了,一發生錯誤就可以拿到錯誤物件裡的message訊息然後印出。
catch (error) {
console.log(error.message);
}
這樣就可以每個驗證都只要丟一個錯誤訊息就好,是不是程式看起來更簡潔美觀了?也不會發生if...else hell了!
其實try...catch還有第三個finally,finally這區塊就是不管怎麼都會去做的一個區塊。
而且try可以只配catch or finally喔,擇一也可以使用。
try {
//要被執行的區塊
} carch(error) {
//要攔截錯誤的區塊
} finally {
//不管錯誤與否都會被執行的區塊
}
好了,大家應該有比較懂try...catch了吧!建議看完我如此白話的文章可以接著看 MDN 會說得更清楚更深入喔!
如果文章有錯誤請throw new Error("打錯拉笨蛋!原因...")給我,謝謝拉!
明天見嚕~
參考資料:過度焦慮的 try-catch
認識 try…catch,處理錯誤
MDN 流程控制與例外處理
MDN try...catch