詳解JavaScript錯(cuò)誤捕獲
一、基本使用與邏輯
使用
try{
//code....
}catch(err){
//error handling
}finally{
//no matter what happens in the try/catch (error or no error), this code in the finally statement should run.
}
邏輯

二、特性
try...catch 僅適用于運(yùn)行時(shí)錯(cuò)誤,解釋階段錯(cuò)誤無(wú)法正常工作
try{
{{{{{{{
}catch(err){
console.error(err)
}
//引擎在‘parse-time'出錯(cuò),導(dǎo)致無(wú)法理解代碼,因此無(wú)法捕捉
try...catch 只能同步工作
try{
setTimeout(function(){
undefinedVariable;
},1000)
}catch(err){
console.error(err)
}
//setTimeout的回調(diào)函數(shù)執(zhí)行時(shí),引擎已經(jīng)離開(kāi)try...catch結(jié)構(gòu)
finally 能讓try塊中的return語(yǔ)句失效
function test(){
try {
return 1;
} catch(error) {
return 2;
} finally {
return 3;
}
}
console.log(test());
//3
三、錯(cuò)誤對(duì)象
當(dāng)程序發(fā)生error,js內(nèi)部會(huì)生成一個(gè)包含error細(xì)節(jié)的對(duì)象,該對(duì)象會(huì)被作為參數(shù)傳進(jìn)catch
對(duì)于所有內(nèi)置錯(cuò)誤,錯(cuò)誤對(duì)象具有兩個(gè)主要屬性
- name 錯(cuò)誤類(lèi)型
- message 文本類(lèi)型的錯(cuò)誤信息
- stack (非標(biāo)準(zhǔn)屬性)發(fā)生錯(cuò)誤時(shí)的調(diào)用棧信息,主要用于調(diào)試
try {
lalala; // error, variable is not defined!
} catch (err) {
alert(err.name); // ReferenceError
alert(err.message); // lalala is not defined
alert(err.stack); // ReferenceError: lalala is not defined at (...call stack)
// Can also show an error as a whole
// The error is converted to string as "name: message"
alert(err); // ReferenceError: lalala is not defined
}
理論上,我們可以throw任何東西作為錯(cuò)誤對(duì)象,但最好的習(xí)慣是throw一個(gè)具有name,message的對(duì)象,以便和內(nèi)置錯(cuò)誤對(duì)象保持兼容
番外:內(nèi)置的錯(cuò)誤對(duì)象
| 對(duì)象 | 含義 |
|---|---|
| ReferenceError | 引用未定義變量時(shí)觸發(fā) |
| SyntaxError | 使用不合法的語(yǔ)法結(jié)構(gòu)時(shí)觸發(fā) |
| TypeError | 值得類(lèi)型非預(yù)期時(shí)觸發(fā) |
| URIError | 錯(cuò)誤使用全局URI函數(shù)如encodeURI()、decodeURI()等時(shí)觸發(fā) |
| RangeError | 對(duì)Array構(gòu)造函數(shù)使用錯(cuò)誤的長(zhǎng)度值,對(duì)Number.toExponential()、Number.toFixed()或Number.toPrecision()使用無(wú)效數(shù)字等 |
| EvalError | 全局函數(shù)eval()中發(fā)生的錯(cuò)誤 |
四、較好的catch和throw策略
catch錯(cuò)誤不單單是為了防止程序掛掉,更重要的目的是方便調(diào)試,找bug,所以對(duì)錯(cuò)誤的處理策略,稍微可以體現(xiàn)出碼者的優(yōu)雅性
俗話(huà)說(shuō)的好,碼者,人恒雅也,盡量遵循一個(gè)原則,catch只處理自己知道的錯(cuò)誤
舉個(gè)梨子
let json = '{ "age": 30 }';
try{
let user = JSON.parse(json);
alert( user.name );
} catch (err) {
console.error('JSON Error:'+err);
}
上述例子的catch策略能保證程序正常,因?yàn)閏atch塊能catch內(nèi)部所有的錯(cuò)誤,無(wú)論是JSON.parse出錯(cuò)還是user.name不存在報(bào)錯(cuò),都能被catch到,但兩種錯(cuò)誤都用同一種打印是不利于調(diào)試的,寫(xiě)成下面這樣會(huì)好一點(diǎn)
let json = '{"age":30}'
try{
let user = JSON.parse(json);
alert(user.name)
}catch(err){
if(err instanceof SyntaxError){
console.error('JSON Error:'+err);
}
else throw err;
}
每個(gè)catch塊處理自己知道得,可能會(huì)出現(xiàn)得錯(cuò)誤,就是說(shuō),編程人員在編程的時(shí)候,catch那些預(yù)料到的錯(cuò)誤,而將可能自己沒(méi)料到的錯(cuò)誤拋到外面。
五、Promise的錯(cuò)誤處理
眾所周知,Promise是會(huì)吞掉error的,因?yàn)閜romise的實(shí)現(xiàn)就在內(nèi)部對(duì)所有error進(jìn)行了捕獲,且捕獲到的error不是向外拋出(外指promise之外),而是沿著鏈找到最近的onreject回調(diào)傳入,所以promise的錯(cuò)誤處理只有兩種辦法
- 設(shè)置onreject回調(diào)
- 全局捕獲
舉個(gè)栗子
try{
new Promise((resolve,reject)=>{
throw new Error('promise error')
}).catch(()=>{
//錯(cuò)誤在最近的onreject回調(diào)被捕獲
console.error(err);
})
}catch(err){
//永遠(yuǎn)不會(huì)執(zhí)行,promise吞掉error
console.error(err);
}
另外需要注意,無(wú)論是執(zhí)行者函數(shù)(executor)和還是 promise 的處理程序(handler),內(nèi)部發(fā)生的錯(cuò)誤統(tǒng)統(tǒng)吞掉,相當(dāng)于被隱式catch,error會(huì)自動(dòng)找到最近的onreject回調(diào)傳進(jìn)去
try{
new Promise((resolve,reject)=>{
resolve();
}).then(()=>{
throw new Error('promise then error');
}).catch((err){
console.error(err);
})
}catch(err){
//地球毀滅之前都不會(huì)執(zhí)行
console.error(err)
}
同理,在錯(cuò)誤找到onreject傳進(jìn)去之前,經(jīng)過(guò)的then注冊(cè)的onfulfilled回調(diào)統(tǒng)統(tǒng)失效,直到找到onreject回調(diào),處理之后,onreject回調(diào)之后的onfulfilled回調(diào)才正常
try {
new Promise((resolve, reject) => {
throw new Error('promise error')
}).then((ret) => {
//錯(cuò)誤沒(méi)有處理,失效
console.log('then1:' + ret)
}).catch((err) => {
//錯(cuò)誤處理了,后序正常
console.error(err);
return 'handled'
}).then((ret) => {
//正常執(zhí)行
console.log('then2' + ret);
})
} catch (err) {
//同樣的,人類(lèi)毀滅之前都不會(huì)執(zhí)行
console.error(err)
}
// Error:promise error
//then2handled
那整條鏈一個(gè)catch都沒(méi)設(shè)置會(huì)怎么樣呢?
那這個(gè)error就會(huì)擊穿地心,一直穿透到全局,根據(jù)宿主環(huán)境的不同觸發(fā)不同的全局事件,比如說(shuō)瀏覽器中會(huì)觸發(fā) unhandledrejection事件,node環(huán)境中也會(huì)觸發(fā)unhandledRejection事件,一般會(huì)對(duì)這事件進(jìn)行監(jiān)聽(tīng),再顯示信息給編程人員或者用戶(hù)
番外1:chromium / v8 / v8 / 3.29.45 的 Promise內(nèi)部錯(cuò)誤捕捉

六、性能損耗
After V8 version 6 (shipped with Node 8.3 and latest Chrome), the performance of code inside try-catch is the same as that of normal code. ------ 爆棧網(wǎng)
(稍微測(cè)了一下,相差無(wú)幾)
以上就是詳解JavaScript錯(cuò)誤捕獲的詳細(xì)內(nèi)容,更多關(guān)于JavaScript 錯(cuò)誤捕獲的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- JavaScript將DOM事件處理程序封裝為event.js 出現(xiàn)的低級(jí)錯(cuò)誤問(wèn)題
- Extjs學(xué)習(xí)過(guò)程中新手容易碰到的低級(jí)錯(cuò)誤積累
- 7個(gè)你應(yīng)該知道的JS原生錯(cuò)誤類(lèi)型
- JavaScript語(yǔ)句錯(cuò)誤throw、try及catch實(shí)例解析
- JS常見(jiàn)錯(cuò)誤(Error)及處理方案詳解
- JS錯(cuò)誤處理與調(diào)試操作實(shí)例分析
- javascript 初學(xué)教程及五子棋小程序的簡(jiǎn)單實(shí)現(xiàn)
- JavaScript初學(xué)者必看“new”
- JavaScript初學(xué)者容易犯的幾個(gè)錯(cuò)誤
相關(guān)文章
JavaScript基礎(chǔ)篇(6)之函數(shù)表達(dá)式閉包
這篇文章主要介紹了javascript基礎(chǔ)篇(6)之函數(shù)表達(dá)式閉包的相關(guān)資料,需要的朋友可以參考下2015-12-12
JavaScript之Map和Set_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了JavaScript之Map和Set的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
在vs2010中調(diào)試javascript代碼方法
只在IE瀏覽器中測(cè)試成功了,在谷歌瀏覽中沒(méi)有測(cè)試成功,其他瀏覽器沒(méi)有測(cè)試。2011-02-02
JS的Ajax與后端交互數(shù)據(jù)的實(shí)例
今天小編就為大家分享一篇JS的Ajax與后端交互數(shù)據(jù)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
javaScript對(duì)文字按照拼音排序?qū)崿F(xiàn)代碼
這篇文章主要介紹了javaScript對(duì)文字按照拼音排序?qū)崿F(xiàn)代碼,有需要的朋友可以參考一下2013-12-12
drag-and-drop實(shí)現(xiàn)圖片瀏覽器預(yù)覽
chrome的drag and drop API,它能將本地的圖片放到瀏覽器中進(jìn)行預(yù)覽,猜想一下當(dāng)我們把圖片拖拽到瀏覽器里會(huì)發(fā)生什么事情,你的瀏覽器試圖打開(kāi)一個(gè)新的頁(yè)面并加載這個(gè)圖片。這篇文章給我們介紹drag-and-drop實(shí)現(xiàn)圖片瀏覽器預(yù)覽,需要的朋友可以參考下2015-08-08

