JS錯誤處理機制2019-08-19(2)

錯誤處理機制

一皆看、Error實例對象

  • JavaScript 解析或運行時悯辙,一旦發(fā)生錯誤帆阳,引擎就會拋出一個錯誤對象。JavaScript 原生提供Error構造函數(shù)氨距,所有拋出的錯誤都是這個構造函數(shù)的實例桑逝。
  • Error實例對象必須有message屬性,表示出錯時的提示信息俏让。Error實例還提供namestack屬性楞遏,分別表示錯誤的名稱和錯誤的堆棧。但它們是非標準的首昔,不是每種實現(xiàn)都有寡喝。
    message:錯誤提示信息
    name:錯誤名稱(非標準屬性)
    stack:錯誤的堆棧(非標準屬性)

Error的六個派生對象:

  • SyntaxError 對象(語法錯誤)
    SyntaxError對象是解析代碼時發(fā)生的語法錯誤。

  • ReferenceError 對象(引用錯誤)
    ReferenceError對象是引用一個不存在的變量時發(fā)生的錯誤勒奇。
    例如:將一個值分配給無法分配的對象预鬓,比如對函數(shù)的運行結果或者this賦值。

  • RangeError 對象(引用錯誤)
    RangeError對象是一個值超出有效范圍時發(fā)生的錯誤
    主要有幾種情況赊颠,一是數(shù)組長度為負數(shù)格二,二是Number對象的方法參數(shù)超出范圍,以及函數(shù)堆棧超過最大值竣蹦。

  • TypeError 對象(類型錯誤)
    TypeError對象是變量或參數(shù)不是預期類型時發(fā)生的錯誤
    例如: 對字符串顶猜、布爾值、數(shù)值等原始類型的值使用new命令

  • URIError 對象(編碼錯誤)
    URIError對象是URI相關函數(shù)的參數(shù)不正確時拋出的錯誤

  • EvalError對象(全局錯誤)
    eval函數(shù)沒有被正確執(zhí)行時草添,會拋出EvalError錯誤驶兜。該錯誤類型已經(jīng)不再使用了,只是為了保證與以前代碼兼容远寸,才繼續(xù)保留抄淑。

以上這6種派生錯誤,連同原始的Error對象驰后,都是構造函數(shù)肆资。開發(fā)者可以使用它們,手動生成錯誤對象的實例灶芝。這些構造函數(shù)都接受一個參數(shù)郑原,代表錯誤提示信息(message)。

二夜涕、throw 語句
throw語句的作用是手動中斷程序執(zhí)行犯犁,拋出一個錯誤。

if (x <= 0) {
  throw new Error('x 必須為正數(shù)');
}
// Uncaught ReferenceError: x is not defined

throw拋出的錯誤就是它的參數(shù)女器,這里是一個Error實例酸役。
throw可以拋出任何類型的值。也就是說,它的參數(shù)可以是任何值涣澡。

// 拋出一個字符串
throw 'Error贱呐!';
// Uncaught Error!

// 拋出一個數(shù)值
throw 42;
// Uncaught 42

// 拋出一個布爾值
throw true;
// Uncaught true

// 拋出一個對象
throw {
  toString: function () {
    return 'Error!';
  }
};
// Uncaught {toString: ?}

對于 JavaScript 引擎來說入桂,遇到throw語句奄薇,程序就中止了

三、try...catch結構

  • 一旦發(fā)生錯誤抗愁,程序就中止執(zhí)行了馁蒂。JavaScript 提供了try...catch結構,允許對錯誤進行處理驹愚,選擇是否往下執(zhí)行远搪。
  • try語句包含了由一個或者多個語句組成的try塊, 和至少一個catch子句或者一個finally子句的其中一個,或者兩個兼有逢捺。
  • 三種形式的try聲明:

1.try...catch

  1. try...finally

  2. try...catch...finally

try {
  throw new Error('出錯了!');
} catch (e) {
  console.log(e.name + ": " + e.message);
  console.log(e.stack);
}
// Error: 出錯了!
//   at <anonymous>:3:9
//   ...
  • catch子句包含try塊中拋出異常時要執(zhí)行的語句谁鳍。即:想讓try語句中的內(nèi)容成功, 如果沒成功劫瞳,想控制接下來發(fā)生的事情倘潜,這時可以在catch語句中實現(xiàn)。 如果在try塊中有任何一個語句(或者從try塊中調(diào)用的函數(shù))拋出異常志于,控制立即轉向catch子句涮因。如果在try塊中沒有異常拋出,會跳過catch子句伺绽。
  • catch代碼塊捕獲錯誤之后养泡,程序不會中斷,會按照正常流程繼續(xù)執(zhí)行下去奈应。
  • catch代碼塊之中澜掩,還可以再拋出錯誤,甚至使用嵌套try...catch結構杖挣。
var n = 100;

try {
  throw n;
} catch (e) {
  if (e <= 50) {
    // ...
  } else {
    throw e;
  }
}
// Uncaught 100
  • catch接受一個參數(shù)肩榕,表示try代碼塊拋出的值。
  • catch代碼塊之中可以加入判斷語句 if...else惩妇。用于判斷錯誤類型株汉,進行不同的處理。
try {
  foo.bar();
} catch (e) {
  if (e instanceof EvalError) {
    console.log(e.name + ": " + e.message);
  } else if (e instanceof RangeError) {
    console.log(e.name + ": " + e.message);
  }
  // ...
}
  • finally子句在try塊和catch之后執(zhí)行但是在下一個try聲明之前執(zhí)行歌殃。無論是否有異常拋出或捕獲它總是執(zhí)行乔妈。

四、finally 代碼塊

  • ry...catch結構允許在最后添加一個finally代碼塊氓皱,表示不管是否出現(xiàn)錯誤褒翰,都必需在最后運行的語句贮懈。
function cleansUp() {
  try {
    throw new Error('出錯了……');
    console.log('此行不會執(zhí)行');
  } finally {
    console.log('完成清理工作');
  }
}

cleansUp()
// 完成清理工作
// Uncaught Error: 出錯了……
//    at cleansUp (<anonymous>:3:11)
//    at <anonymous>:10:1

上面代碼中,由于沒有catch語句塊优训,一旦發(fā)生錯誤,代碼就會中斷執(zhí)行各聘。中斷執(zhí)行之前揣非,會先執(zhí)行finally代碼塊,然后再向用戶提示報錯信息躲因。

function idle(x) {
  try {
    console.log(x);
    return 'result';
  } finally {
    console.log('FINALLY');
  }
}

idle('hello')
// hello
// FINALLY

上面代碼中早敬,try代碼塊沒有發(fā)生錯誤,而且里面還包括return語句大脉,但是finally代碼塊依然會執(zhí)行搞监。而且,這個函數(shù)的返回值還是result镰矿。

  • return語句的執(zhí)行是排在finally代碼之前琐驴,只是等finally代碼執(zhí)行完畢后才返回。
  • 下面是finally代碼塊用法的典型場景秤标。
openFile();

try {
  writeFile(Data);
} catch(e) {
  handleError(e);
} finally {
  closeFile();
}

上面代碼首先打開一個文件绝淡,然后在try代碼塊中寫入文件,如果沒有發(fā)生錯誤苍姜,則運行finally代碼塊關閉文件牢酵;一旦發(fā)生錯誤,則先使用catch代碼塊處理錯誤衙猪,再使用finally代碼塊關閉文件馍乙。

  • try...catch...finally這三者之間的執(zhí)行順序,例:
function f() {
  try {
    console.log(0);
    throw 'bug';
  } catch(e) {
    console.log(1);
    return true; // 這句原本會延遲到 finally 代碼塊結束再執(zhí)行
    console.log(2); // 不會運行
  } finally {
    console.log(3);
    return false; // 這句會覆蓋掉前面那句 return
    console.log(4); // 不會運行
  }

  console.log(5); // 不會運行
}

var result = f();
// 0
// 1
// 3

result
// false

上面例子中catch代碼塊結束執(zhí)行之前,會先執(zhí)行finally代碼塊垫释。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丝格,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子饶号,更是在濱河造成了極大的恐慌铁追,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茫船,死亡現(xiàn)場離奇詭異琅束,居然都是意外死亡,警方通過查閱死者的電腦和手機算谈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進店門涩禀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人然眼,你說我怎么就攤上這事艾船。” “怎么了?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵屿岂,是天一觀的道長践宴。 經(jīng)常有香客問我,道長爷怀,這世上最難降的妖魔是什么阻肩? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮运授,結果婚禮上烤惊,老公的妹妹穿的比我還像新娘。我一直安慰自己吁朦,他們只是感情好柒室,可當我...
    茶點故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著逗宜,像睡著了一般雄右。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锦溪,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天不脯,我揣著相機與錄音,去河邊找鬼刻诊。 笑死防楷,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的则涯。 我是一名探鬼主播复局,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼粟判!你這毒婦竟也來了亿昏?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤档礁,失蹤者是張志新(化名)和其女友劉穎角钩,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體呻澜,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡递礼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了羹幸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脊髓。...
    茶點故事閱讀 40,918評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖栅受,靈堂內(nèi)的尸體忽然破棺而出将硝,到底是詐尸還是另有隱情恭朗,我是刑警寧澤,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布依疼,位于F島的核電站痰腮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏律罢。R本人自食惡果不足惜诽嘉,卻給世界環(huán)境...
    茶點故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望弟翘。 院中可真熱鬧,春花似錦骄酗、人聲如沸稀余。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽睛琳。三九已至,卻和暖如春踏烙,著一層夾襖步出監(jiān)牢的瞬間师骗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工讨惩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辟癌,地道東北人。 一個月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓荐捻,卻偏偏與公主長得像黍少,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子处面,可洞房花燭夜當晚...
    茶點故事閱讀 45,926評論 2 361

推薦閱讀更多精彩內(nèi)容