1. Error 實例對象數組
JavaScript 解析或運行時,一旦發生錯誤,引擎就會拋出一個錯誤對象。函數
JavaScript 原生提供Error
構造函數,全部拋出的錯誤都是這個構造函數的實例。this
var err = new Error('出錯了'); err.message // "出錯了"
拋出Error
實例對象之後,整個程序就中斷在發生錯誤的地方,再也不往下執行spa
function throwit() { throw new Error(''); } function catchit() { try { throwit(); } catch(e) { console.log(e.stack); // print stack trace } } catchit()
// Error // at throwit (~/examples/throwcatch.js:9:11) // at catchit (~/examples/throwcatch.js:3:9) // at repl:1:5
// 錯誤堆棧的最內層是 函數
// 而後是 函數
// 最後是函數的運行環境throwitcatchit
Error
實例還提供name
和stack
屬性,分別表示錯誤的名稱和錯誤的堆棧,但它們是非標準的,不是每種實現都有
2. 原生錯誤類型prototype
Error
實例對象是最通常的錯誤類型,code
在 Error 的基礎上,JavaScript 還定義了 Error 的 6 個派生對象對象
// 開發者可使用它們,手動生成錯誤對象的實例 var err1 = new Error('出錯了!'); var err2 = new RangeError('出錯了,變量超出有效範圍!'); var err3 = new TypeError('出錯了,變量類型無效!'); err1.message // "出錯了!" err2.message // "出錯了,變量超出有效範圍!" err3.message // "出錯了,變量類型無效!"
SyntaxError
對象 是解析代碼時發生的語法錯誤
// 變量名錯誤 var 1a; // Uncaught SyntaxError: Invalid or unexpected token // 缺乏括號 console.log 'hello'); // Uncaught SyntaxError: Unexpected string // 上面代碼的錯誤,都是在語法解析階段就能夠發現,因此會拋出 SyntaxError // 第一個錯誤提示是「token 非法」, // 第二個錯誤提示是「字符串不符合要求」
ReferenceError
對象 是引用一個不存在的變量時發生的錯誤
RangeError
對象 是一個值超出有效範圍時發生的錯誤。
Number
對象的方法參數超出範圍
TypeError
對象 是變量或參數不是預期類型時發生的錯誤
new
命令, 就會拋出這種錯誤,由於new
命令的參數應該是一個構造函數TypeError
錯誤
URIError
對象 是 URI 相關函數的參數不正確時拋出的錯誤
encodeURI()
、decodeURI()
、encodeURIComponent()
、decodeURIComponent()
、escape()
和unescape()這六個函數
EvalError
對象 是 eval函數 沒有被正確執行時,會拋出 EvalError
3. 自定義錯誤blog
除了 JavaScript 原生提供的七種錯誤對象,還能夠定義本身的錯誤對象繼承
function UserError(message) {
this.message = message || '默認信息';
this.name = 'UserError';
}
UserError.prototype = new Error();
UserError.prototype.constructor = UserError;
// 上面代碼自定義一個錯誤對象,讓它繼承對象。而後,就能夠生成這種自定義類型的錯誤了
UserErrorErrorvar mineErr = new UserError('這是自定義的錯誤!');
// throw
也能夠拋出自定義錯誤
throwthrow new UserError('出錯了!');
4. throw 中斷程序,拋出錯誤token
throw
語句的做用是手動中斷程序執行,拋出一個錯誤
if (x <= 0) { throw new Error('x 必須爲正數'); } // Uncaught ReferenceError: x is not defined
hrow
能夠拋出任何類型的值。也就是說,它的參數能夠是任何值throw
拋出的信息,多是一個錯誤實例,也多是其餘類型的值
5. try...catch
JavaScript 提供了try...catch
結構,容許對錯誤進行處理,選擇是否往下執行
try
代碼塊拋出錯誤(上例用的是throw
語句),JavaScript 引擎就當即把代碼的執行,轉到catch
代碼塊,或者說錯誤被catch
代碼塊捕獲了。catch
接受一個參數,表示try
代碼塊拋出的值
try { throw new Error('出錯了!'); } catch (e) { console.log(e.name + ": " + e.message); console.log(e.stack); } // Error: 出錯了! // at <anonymous>:3:9 // ...
catch
代碼塊捕獲錯誤以後,程序不會中斷,會按照正常流程繼續執行下去
try { throw "出錯了"; } catch (e) { console.log(111); } console.log(222); // 111 // 222
catch
代碼塊之中,還能夠再拋出錯誤,甚至使用嵌套的try...catch
結構
var n = 100; try { throw n; } catch (e) { if (e <= 50) { // ... } else { throw e; } } // Uncaught 100
catch
代碼塊之中能夠加入判斷語句
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); } // ... }EvalErrorRangeError
6. finnally 代碼塊
try...catch
結構容許在最後添加一個finally
代碼塊,表示無論是否出現錯誤,都必需在最後運行的語句
function cleansUp() { try { throw new Error('出錯了……'); console.log('此行不會執行'); } finally { console.log('完成清理工做'); } } cleansUp() // 完成清理工做 // Error: 出錯了……
finally
代碼塊用法的典型場景
openFile(); try { writeFile(Data); } catch(e) { handleError(e); } finally { closeFile(); }
首先打開一個文件,而後在try
代碼塊中寫入文件,若是沒有發生錯誤,則運行finally
代碼塊關閉文件;一旦發生錯誤,則先使用catch
代碼塊處理錯誤,再使用finally
代碼塊關閉文件
try...catch...finally
這三者之間的執行順序
function f() { try { console.log(0); throw 'bug'; } catch(e) { console.log(1); return true; // 這句本來會延遲到 finally 代碼塊結束再執行 console.log(2); // 不會運行 } finally { console.log(3); return false; // 這句會覆蓋掉前面那句 return console.log(4); // 不會運行 } console.log(5); // 不會運行 } var result = f(); // 0 // 1 // 3 result // false