javascript異常
所謂異常就是程序的非正常運行,通俗的說就是程序發(fā)生了錯誤。至于這些錯誤,有的是認(rèn)為疏忽造成的異常(Exception),有的是程序本身的錯誤(Error)。
比如有的時候我們希望兩個數(shù)相加,因為人為疏忽,代碼里寫成了乘號,那么這種錯誤大部分情況下是得不到你想要的結(jié)果的,但是幸運又不幸的是,這個程序沒有語法錯誤,依然可以返回結(jié)果,但是無法報錯。
另一種情況就是你的程序無法被JavaScript引擎執(zhí)行,這種異常引擎會拋出一個異常,這個時候如果你沒有捕獲異常,那么程序就會被中斷,無法執(zhí)行下去。
code1:
alert('js運行了!')
let a = b + 1
alert('程序結(jié)束')

這個時候我們的瀏覽器客戶端作為JavaScript引擎就會捕獲一條異常報告,俗稱報錯了。
因為此時代碼中的 b 是尚未定義的,拋出了ReferenceError這個異常,下面是JavaScript中經(jīng)常遇到的異常類型,大概分類有如下幾種:
- EvalError: raised when an error occurs executing code in eval()
- RangeError: raised when a numeric variable or parameter is outside of its valid range
- ReferenceError: raised when de-referencing an invalid reference
- SyntaxError: raised when a syntax error occurs while parsing code in eval()
- TypeError: raised when a variable or parameter is not a valid type
- URIError: raised when encodeURI() or decodeURI() are passed invalid parameters
上面的六種異常對象都繼承自Error對象。他們都支持以下兩種構(gòu)造方法: new Error();
new Error(“異常信息”);
try/catch/finlly語句
上面介紹了幾種程序拋出的異常,那么現(xiàn)在就需要對異常進(jìn)行處理,其中try從句中定義了需要處理和判斷的代碼塊,catch從句中放置當(dāng)程序發(fā)生異常后進(jìn)行處理的代碼,catch從句后跟隨finally塊,finally中放置清理代碼,不管try塊中是否產(chǎn)生異常。finally塊中的邏輯代碼都會執(zhí)行,其中catch和finally都是可選的,但是必須選擇兩種中之一和try從句組成完整的語句。
try、catch、finally語句塊都需要使用花括號括起來,即使語句中只有一條語句也不能省略,記住,這里的花括號是必須的
下面的代碼說明了try/catch/finlly語句的用法和作用
try {
// 這里是你可能會出現(xiàn)異常的代碼
// 可以通過throw直接拋出異常
// 或者通過調(diào)用一個方法間接拋出
} catch(e) {
// 當(dāng)try語句塊拋出了異常,這里的代碼就會執(zhí)行
// 可以通過局部變量e來獲取該異常Error對象的信息
// 可以通過throw重新拋出異常
} finally {
// 無論是否拋出異常,都會執(zhí)行這里的代碼
// 終止語句塊的方法有:
// 1. 正常執(zhí)行最后一條語句終止
// 2. 通過break、continue、或return終止
// 3. 拋出異常,被try捕獲
// 4. 拋出異常,異常未被捕獲,繼續(xù)向上傳播
}
我們看到,catch后面接了個標(biāo)識符e,這個標(biāo)識符和函數(shù)參數(shù)很想,當(dāng)捕獲一個異常時,把和這個異常相關(guān)的值(比如Error對象)賦值給這個參數(shù),和普通的變量不同,這條catch句中的標(biāo)識符具有塊級作用域,它只在catch語塊內(nèi)有定義。這個Error對象有幾個主要屬性,如下:
- description: 錯誤描述 (僅IE可用).
- fileName: 出錯的文件名 (僅Mozilla可用).
- lineNumber: 出錯的行數(shù) (僅Mozilla可用).
- message: 錯誤信息 (在IE下同description)
- name: 錯誤類型.
- number: 錯誤代碼 (僅IE可用).
- stack: 像Java中的Stack Trace一樣的錯誤堆棧信息 (僅Mozilla可用).
下面就使用一個try/catch語句把pic1中的代碼包裹起來
try{
//這里放置可能會出錯的代碼
let a = b + 1
} catch(e)
{
//代碼出錯后執(zhí)行這里。
console.debug(' name: ' + e.name +
' message: ' + e.message +
' lineNumber: ' + e.lineNumber +
' fileName: ' + e.fileName +
' stack: ' + e.stack);
} finally {
console.log('執(zhí)行了finally')
}
將上面的代碼復(fù)制到chrome控制臺,會看到下面的信息,說明異常已經(jīng)被捕獲,并且,最終執(zhí)行了finally

通常狀況下,解釋器執(zhí)行到try語句塊的尾部,然后開始執(zhí)行finally中的代碼,以便進(jìn)行必要的清理工作。當(dāng)由于return、continue、break語句使得解釋器跳出try語句塊時,解釋器在執(zhí)行新的目標(biāo)代碼之前先執(zhí)行finally中的代碼。
如果在try中產(chǎn)生了異常,而且存在一條與之相關(guān)的catch從句來處理這個異常,解釋器首先執(zhí)行catch中的邏輯,然后執(zhí)行finally中的邏輯,如果不存在處理異常的局部catch從句,解釋器會首先執(zhí)行finally中的邏輯,然后向上傳播異常,直到找到能處理這個異常的catch從句。
如果finally快使用了return、continue、break或者throw語句時程序發(fā)生跳轉(zhuǎn),或者通過調(diào)用了拋出異常的方法改變了程序執(zhí)行流程,不管這個跳轉(zhuǎn)使程序掛起還是繼續(xù)執(zhí)行,解釋器都會將其忽略。例如finally從句拋出一個異常,這個異常將替代正在拋出的異常。如果finally從句運行倒了return語句,盡管已經(jīng)拋出了異常且這個異常還沒有處理,這個方法依然會正常返回。
throw語句
在JavaScript運行的時候,若使用throw語句時就會電視的拋出異常。
throw語句的語法如下:
throw expression
expression的值是任意類型的??梢話伋龃礤e誤碼的數(shù)字亦或是讓人明白意思的字符串。JavaScript解釋器拋出異常的時候通常采用Error類型和其子類型。
function getMoney(money) {
// 若傳入的參數(shù)非法,直接拋出異常
if (money < 0)
throw new Error('金額不能為負(fù)數(shù)')
return money
}
在chrome控制臺里試試,這個時候如果傳入的參數(shù)小于0就會直接拋出一個自定義字符串的異常了,見下圖:

最后
當(dāng)程序拋出異常時,JavaScript解釋器會立即停止當(dāng)前正在執(zhí)行的邏輯,并跳轉(zhuǎn)至就近的異常處理程序,如果拋出異常的代碼塊中沒有try/catch語句,解釋器會檢查更高層次的閉合代碼塊,看它是否有關(guān)聯(lián)異常處理程序。以此類推,直到找到異常處理程序為止