JS中異常拋出和處理方法圖文詳解
拋出異常
在 js 中,有時(shí)候我們需要處理一些異?;蝈e(cuò)誤。比如編寫(xiě)的某個(gè)函數(shù)所接收的參數(shù)要求是 Number 類型的,如果在該函數(shù)被調(diào)用時(shí)傳入的是字符串,就需要發(fā)出提醒。此時(shí)我們可以使用 throw 語(yǔ)句來(lái)拋出個(gè)異常:
// 例 1 function fn(num) { if (typeof num !== 'number') throw '需傳入數(shù)字' console.log(num) // 不會(huì)打印 } fn('0') console.log('不會(huì)執(zhí)行')
執(zhí)行例 1 的代碼結(jié)果如下:
因?yàn)榈?7 行傳入的是字符串,所以會(huì)導(dǎo)致第 3 行 throw
語(yǔ)句的執(zhí)行,那么在函數(shù) fn 內(nèi),之后的語(yǔ)句就不會(huì)執(zhí)行了,這點(diǎn)和 return
一樣。因?yàn)槲覀儧](méi)有對(duì)第 7 行的 fn 函數(shù)的執(zhí)行做異常捕獲的操作,所以程序終止,其后的第 8 行也不會(huì)執(zhí)行。
拋出的表達(dá)式類型
基本數(shù)據(jù)類型
例 1 中我們就是是拋出了一個(gè)基本數(shù)據(jù)類型 —— 字符串,當(dāng)然還可以是數(shù)字等其它基本類型的數(shù)據(jù)。
對(duì)象
我們也可以拋出一個(gè)對(duì)象,這樣可以傳遞更多的信息:
// 例 1.1 function fn(num) { if (typeof num !== 'number') throw { code: -1, msg: '類型錯(cuò)誤' } console.log(num) }
類的實(shí)例對(duì)象
如果每次拋出異常我們都像例 1.1 這樣寫(xiě)個(gè)對(duì)象會(huì)比較繁瑣,所以可以創(chuàng)建一個(gè)類,比如例 1.2 的 myError
,幫我們創(chuàng)建包含了錯(cuò)誤信息的對(duì)象:
// 例 1.2 class myError { constructor(code, msg) { this.code = code this.msg = msg } } function fn(num) { if (typeof num !== 'number') throw new myError(-1, '類型錯(cuò)誤') console.log(num) }
這樣執(zhí)行 fn 時(shí),如果不做異常捕獲就會(huì)打印如下的報(bào)錯(cuò)信息:
Error 類的實(shí)例對(duì)象
事實(shí)上我們并不需要自己定義一個(gè)類來(lái)創(chuàng)建錯(cuò)誤對(duì)象,js 本身就為我們提供了這么一個(gè)類 Error
,構(gòu)建錯(cuò)誤對(duì)象時(shí)傳入錯(cuò)誤的描述信息即可:
// 例 1.3 function fn(num) { if (typeof num !== 'number') throw new Error('類型錯(cuò)誤') console.log(num) } fn('0')
在 node 中執(zhí)行例 1.3,得到的結(jié)果會(huì)比我們自己定義的 myError
多出函數(shù)的調(diào)用棧的信息:
我們可以直接通過(guò) Error
實(shí)例對(duì)象的 stack
屬性查看調(diào)用棧,還有 message
和name
:
// 例 1.3.1 function fn(num) { if (typeof num !== 'number') { const err = new Error('類型錯(cuò)誤') console.log('name:', err.name) console.log('message:', err.message) console.log('stack:', err.stack) throw err } console.log(num) } fn('0')
在 node 中執(zhí)行例 1.3.1,第 5 ~ 7 的輸出結(jié)果如下:
如果我們對(duì)例 1.3 進(jìn)行些改造,不直接執(zhí)行 fn('0')
而是讓它在 bar 函數(shù)內(nèi)被調(diào)用,然后在 foo 函數(shù)內(nèi)調(diào)用 bar ,最后執(zhí)行 foo()
:
// 例 1.3.2 function fn(num) { if (typeof num !== 'number') throw new Error('類型錯(cuò)誤') console.log(num) } function foo() { bar() } function bar() { fn('0') } foo()
就可以看到調(diào)用棧信息又多了 2 條:
Error 的子類
Error 還有幾個(gè)子類,比如上面的這些例子,因?yàn)閷儆陬愋湾e(cuò)誤,所以可以用更具體的 TypeError
類來(lái)生成錯(cuò)誤對(duì)象:
// 例 1.4 function fn(num) { if (typeof num !== 'number') throw new TypeError('類型錯(cuò)誤') console.log(num) } fn('0')
另外還有諸如引用錯(cuò)誤 ReferenceError
和語(yǔ)法錯(cuò)誤 SyntaxError
等。
處理異常
若一個(gè)異常被拋出而最終沒(méi)有被捕獲,那么會(huì)導(dǎo)致程序的終止執(zhí)行。之所以加了“最終”兩個(gè)字,是因?yàn)槿绻瘮?shù)執(zhí)行時(shí)拋出的異常沒(méi)有被處理,異常會(huì)傳遞給執(zhí)行了該函數(shù)的函數(shù)調(diào)用。以例 1.3.2 為例,第 10 行執(zhí)行 fn('0')
導(dǎo)致拋出了異常,我們又沒(méi)有在第 10 行對(duì)fn('0')
進(jìn)行異常捕獲,那么異常就會(huì)傳給第 7 行的 bar()
,再傳給第 12 行,也就是最頂層的 foo()
,此時(shí)還是沒(méi)有對(duì)異常進(jìn)行處理,才會(huì)導(dǎo)致報(bào)錯(cuò)并終止程序的運(yùn)行。 只要我們?cè)诋惓鬟f過(guò)程中的任何一處用 try...catch
語(yǔ)句對(duì)異常進(jìn)行了捕獲,比如下面的例 2,那么程序就不會(huì)被終止,異常會(huì)作為參數(shù)傳遞給 catch
子句,也就是第 15 行的 error
:
// 例 2 function fn(num) { if (typeof num !== 'number') throw new Error('類型錯(cuò)誤') console.log(num) // 不會(huì)執(zhí)行 } function foo() { bar() } function bar() { fn('0') } try { foo() console.log('我不會(huì)繼續(xù)執(zhí)行') } catch (error) { console.log('error:', error.message) } finally { console.log('我無(wú)論是否有異常拋出都會(huì)執(zhí)行') } console.log('我會(huì)繼續(xù)執(zhí)行')
執(zhí)行例 2 的結(jié)果如下:
可以看到例 2 第 17 行還有個(gè) finally
子句,無(wú)論是否有異常拋出或捕獲它總是執(zhí)行。
P.S. 從 ES10(ES2019)開(kāi)始,第 15 行的 catch
子句可以省略掉 (error)
,也就是不去獲取錯(cuò)誤信息。
js中常見(jiàn)的系統(tǒng)異常:
- EvalError: raised when an error occurs executing code in eval() 當(dāng)一個(gè)錯(cuò)誤發(fā)生在()執(zhí)行的代碼
- RangeError: raised when a numeric variable or parameter is outside of its valid range 當(dāng)一個(gè)數(shù)值變量或參數(shù)超出其有效范圍時(shí)引發(fā)的
- ReferenceError: raised when de-referencing an invalid reference 無(wú)效的飲用
- SyntaxError: raised when a syntax error occurs while parsing code in eval() 當(dāng)發(fā)生語(yǔ)法錯(cuò)誤在()解析代碼,而
- TypeError: raised when a variable or parameter is not a valid type 當(dāng)一個(gè)變量或參數(shù)不是一個(gè)有效的類型時(shí)引發(fā)
- URIError: raised when encodeURI() or decodeURI() are passed invalid parameters 當(dāng)encodeuri()或decodeuri()傳遞了無(wú)效的參數(shù)
注:上面的六種異常對(duì)象都繼承自Error對(duì)象:
try { throw new Error("Whoops!"); } catch (e) { console.log(e.name + ": " + e.message); }
總結(jié)
到此這篇關(guān)于JS中異常拋出和處理方法的文章就介紹到這了,更多相關(guān)JS異常拋出與處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript學(xué)習(xí)之談?wù)凧S的全局變量跟局部變量(推薦)
這篇文章主要介紹了Javascript學(xué)習(xí)之談?wù)凧S的全局變量跟局部變量雖然腳本之家小編以前發(fā)過(guò),但還是這篇文章整理的比較好,需要的朋友可以參考一下2016-08-08Javascript 兩種刷新方法以及區(qū)別和適用范圍
這篇文章主要介紹了Javascript 兩種刷新方法以及區(qū)別和適用范圍的相關(guān)資料,需要的朋友可以參考下2017-01-01JavaScript運(yùn)動(dòng)框架 多物體任意值運(yùn)動(dòng)(三)
這篇文章主要為大家詳細(xì)介紹了JavaScript運(yùn)動(dòng)框架的第三部分,多物體任意值運(yùn)動(dòng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05微信小程序?qū)W習(xí)筆記之獲取位置信息操作圖文詳解
這篇文章主要介紹了微信小程序?qū)W習(xí)筆記之獲取位置信息操作,結(jié)合實(shí)例形式分析了微信小程序獲取位置信息的原理、步驟及相關(guān)操作注意事項(xiàng),并結(jié)合圖文形式予以說(shuō)明,需要的朋友可以參考下2019-03-03