https://github.com/Ray-D-Song
錯誤和異常是從實踐中誕生的概念,旨在處理「可編程錯誤」。
從程式碼角度來看,錯誤往往會被手動精確處理。
例如,fnA 呼叫 fnB 和 fnC。兩種方法都可能遇到錯誤,處理程式碼大致如下:
function fnA() { const { err: bErr, res: bRes } = fnB() if (bErr) { // ... // error handling } const { err: cErr, res: cRes } = fnC() if (cErr) { // ... // error handling } // normal logic }
「錯誤」的關鍵是從函數傳回一個物件或數組,其中一個字段代表「發生錯誤」。只要這個欄位不為空,程式設計師就知道正常的流程被中斷了。
JavaScript 有一個內部 Error 物件和建構函數,但表示錯誤的欄位不需要是 Error 物件。相反,Error 物件更常用於異常處理。
我們已經有錯誤處理,為什麼還需要異常了?
想像一個場景,你有一個按鈕。當按鈕被點擊時,會觸發函數A,經過多層呼叫(可能是10層),函數X出現錯誤。你不想告訴用戶“未知錯誤”,而是想提供有關問題所在的具體資訊。
你可以透過錯誤來實現這個效果,但你需要寫十次這樣的程式碼:
function fnA() { const { err, res } = fnB() if (err) { // display error to user showErr(err) } } function fnB() { const { err, res } = fnC() if (err) // propagate error return { err, null } } // ... 10 similar passes function fnY() { const { err, res } = fnX() if (err) // propagate error return { err, null } }
這種樣板程式碼效率很低。更好的方法是使用異常。
只需要在fnY發生錯誤時拋出異常即可。在頂層,你可以抓住它。
function fnA() { try { fnB() } catch (e) { showErr(e) } } // ... function fnY() { const { err, res } = fnX() if (err) // 抛出 throw err }
這樣,無論哪裡發生錯誤,都可以在頂層捕獲,並且其他層的程式碼不受影響。
避免一處錯誤污染整個程式碼結構。
我們已經解釋了為什麼需要異常,但是為什麼需要區分錯誤和異常呢?
最好的做法是嚴格區分兩者。如果錯誤不需要逐層向上傳遞,則應直接在目前層進行處理。例如fnC的錯誤不需要在fnA使用,所以應該直接在B當錯誤處理。
假設所有錯誤都在頂層處理,那麼所有邏輯都堆積在頂層的catch塊中,很難維護。
function main() { try { task1() task2() task3() } catch(e) { switch(e) { case "type A": //... break; case "type B": //... break; case "type C": //... break; } } }
以上是JavaScript 中錯誤和異常的區別的詳細內容。更多資訊請關注PHP中文網其他相關文章!