在ES3之前js代碼執行的過程中,一旦出現錯誤,整個js代碼都會停止執行,這樣就顯的代碼非常的不健壯。
在Java或C#等一些高級語言中,都提供了異常處理機制,可以處理出現的異常,而不會停止整個應用程序。
從ES3開始,js也提供了類似的異常處理機制,從而讓js代碼變的更健壯,及時執行的過程中出現了異常,也可以讓程序具有了一部分的異常恢復能力。
一、Javascript的異常捕獲機制
1.1 基本的try…catch語句
ES3開始引入了 try-catch 語句,是 JavaScript 中處理異常的標準方式。
語法:
try{
//可能發生異常的代碼
}catch(error){
//發生錯誤執行的代碼
}
看下面的代碼:
<script>
try{
console.log(b);
console.log("我不會輸出的,不要找了")
}catch(error){
console.log("發生錯誤了")
}
console.log("我try catch後面的代碼")
</script>
說明:
- 把有可能出的問題的代碼放在 try 語句中。try語句中可以理論上可以寫任何的代碼,只要有一行代碼出現問題,整個程序的執行流程就會立即調到catch語句中執行。
- 一旦try中有一行代碼發生異常,則這行出錯代碼的後面的try中的其他語句都不會再執行。比如上面代碼中的
console.log(b);
這行代碼會出錯,則立即去執行catch中的代碼。所以console.log("我不會輸出的,不要找了")
這行代碼則不會再執行 - 在執行catch中的代碼之前,js引擎會首先根據錯誤類型自動創建一個錯誤,並通過catch後面的參數傳遞到catch中。不同的瀏覽器創建的error對象不一樣,但是同創他們都包含一個message屬性,值是這個錯誤的一些信息。
- catch中的代碼執行完畢之後,會繼續執行後面的代碼,程序不會停止下來。
1.2 finally語句
在 try…catch 中,try 中一旦出現錯誤則其他語句不能執行,如果不出現錯誤則 catch 中的語句不會執行。
Javascript 參考其他編程語言,也提供了一種 finally 語句:不管 try 中的語句有沒有錯誤,在最後都會執行 finally 中的語句。
即:try 中語句不發生錯誤執行完畢後會執行 finally 中的語句,try 中的語句發生錯誤,則執行 catch中的語句,catch 中的語句執行完畢後也會執行 finally 中的語句。
語法:
try{
}catch(error){
}finally{
}
<script>
try{
console.log(b);
console.log("我不會輸出的,不要找了")
}catch(error){
console.log("發生錯誤了")
}finally {
console.log("不管發生不發生錯誤,我都會執行")
}
console.log("我try catch後面的代碼")
</script>
所以在 finally 中我們可以放置我們必須要執行的代碼。
注意:
- 在js中,如果添加了 finally 語句,則 catch 語句可以省略。所以下面的代碼也是正確的。
- 如果沒有 catch 語句,則一旦發生錯誤就無法捕獲這個錯誤,所以在執行完 finally 中的語句後,程序就會立即停止了。
- 所以,在實際使用中,最好一直帶着 catch 語句。
<script>
try{
console.log(b);
console.log("我不會輸出的,不要找了")
}finally {
console.log("不管發生不發生錯誤,我都會執行")
}
console.log("我try catch後面的代碼")
</script>
1.3 js中的錯誤類型
執行代碼期間可能會發生的錯誤有多種類型。每種錯誤都有對應的錯誤類型,而當錯誤發生時,就 會拋出相應類型的錯誤對象。js共定義了下列 7 種錯誤類型:
- Error ‰
- EvalError
- RangeError ‰
- ReferenceError ‰
- SyntaxError ‰
- TypeError ‰
- URIError
說明:
- Error類型是基本的錯誤類型,其他類型都繼承自這個類型。
- EvalError 類型的錯誤會在使用 eval()函數而發生異常時被拋出
- TypeError 類型在 JavaScript 中會經常用到,在變量中保存着意外的類型時,或者在訪問不存在的 方法時,都會導致這種錯誤
- 一般情況,不同的錯誤,處理方式不一樣。可以參考下面的處理方式。不過在實際開發中,很多程序員並沒有形成處理錯誤的習慣。
try {
someFunction();
} catch (error){
if (error instanceof TypeError){
//處理ૌ類型錯誤
} else if (error instanceof ReferenceError){
//處理引用錯誤
} else {
//處理其他的錯誤
}
}
1.4 合理使用try…catch
當 try-catch 語句中發生錯誤時,瀏覽器會認爲錯誤已經被處理了,瀏覽器就不再報告錯誤了。這也是最簡單的一種情況。
使用 try-catch 最適合處理那些我們無法控制的錯誤。假設你在使用一個大型 JavaScript 庫中的 函數,該函數可能會有意無意地拋出一些錯誤。由於我們不能修改這個庫的源代碼,所以大可將對該函 數的調用放在 try-catch 語句當中,一有什麼錯誤發生,也好可以恰當地處理它們。
在明明知道自己的代碼會發生錯誤時,再使用 try-catch 語句就不太合適了。例如,如果 傳給函數的參數是字符串而非數值,就會造成函數出錯,那麼就應該先檢查參數的類型,然後再決定 如何去做。在這種情況下,不應用使用 try-catch 語句。因爲try…catch語句比較是比較好資源的事情。
二、throw主動拋出異常
2.1 拋出js內置錯誤類型的對象
在大部分的代碼執行過程中,都是出現錯誤的時候,由瀏覽器(javascript引擎)拋出異常,然後程序或者停止執行,或被try…catch 捕獲。
然而有時候我們在檢測到一些不合理的情況發生的時候也可以主動拋出錯誤。
使用 throw 關鍵字拋出來主動拋出異常。
<script>
throw new Error("你好壞");
console.log("執行不到這裏的")
</script>
注意:
- thow後面就是我們要拋出的異常對象。在以前的時候都是出現錯誤的時候瀏覽器拋出異常對象,只是現在是我們自己主動拋出的異常對象。
- 只要有異常對象拋出,不管是瀏覽器拋出的,還是代碼主動拋出,都會讓程序停止執行。如果想讓程序繼續執行,則有也可以用try…catch來捕獲。
- 每一個錯誤類型都可以傳入一個參數,表示實際的錯誤信息。
- 我們可以在適當的時候拋出任何我們想拋出的異常類型。
throw new SyntaxError("語法錯誤...");
看下面的代碼:
<script>
/*該函數接收一個數字,返回他的平方。*/
function foo(num) {
if(typeof num == "number"){
return num * num;
}else{
throw new TypeError("類型錯誤,你應該傳入一個數字...")
}
}
console.log(foo(33))
console.log(foo("abc"))
</script>
2.2 拋出自定義類型的錯誤對象
我們不僅僅可以拋出js內置的錯誤類型的對象,也可以自定義錯誤類型,然後拋出自定義錯誤類型的對象。
如果要自定義錯誤類型,只需要繼承任何一個自定義錯誤類型都可以。一般直接繼承Error即可。
<script>
function MyError(message) {
this.message = "注意:這是自定義的錯誤"
this.name = "自定義錯誤";
}
MyError.prototype = new Error();
try {
throw new MyError("注意:這是自定義錯誤類型")
}catch (error){
console.log(error.message)
}
</script>