## 錯誤處理機制
**1、 try-catch語句**
ECMA-262第3版引入了`try-catch`語句,作為JavaScript中處理異常的一種標準方式。
語法:
```
try{
// 可能會導致錯誤的代碼
}catch (error){
// 在錯誤發生時怎么處理
}
```
也就是說,我們應該把所有可能會拋出錯誤的代碼都放在try語句塊中,而把那些用于錯誤處理代碼放在catch塊中。
`try-catch`語句的邏輯是:如果try塊中的任何代碼發生了錯誤,就會立即退出代碼執行過程,然后接著執行catch塊。此時,catch塊會接收到一個包含錯誤信息的對象。
注意:即使你不想使用這個錯誤對象,也要給它起個名字。
雖然這個對象在不同瀏覽器中可能包含不同信息,但是都有一個保存著錯誤消息的message屬性,還有一個保存錯誤類型的name屬性(并不是所有瀏覽器都有)。
```
try{
}catch (error){
console.log(error.message);
}
```
在跨瀏覽器編程時,最好還是只使用message屬性。
**1.1 finally子句**
當使用`finally`子句時,其代碼無論如何都會執行,也就是說,不管是正常執行還是出錯了,`finally`子句都會執行。甚至`return`語句,也不會阻止`finally`子句的執行。
看下面的例子:
```
function test(){
try{
console.log('a');
return 2;
}catch(error){
console.log('b');
}finally{
console.log('c');
}
}
console.log(test());
//結果
a
c
2
```
從運行結果,我們可以看到,`return`語句并沒有阻止`finally`子句的執行,而且是在`finally`子句執行后才會返回`return`語句的值。
**2、錯誤類型**
執行代碼期間可能會發生的錯誤有多種類型。每種錯誤都有對應的錯誤類型,而當錯誤發生時,會拋出相應類型的錯誤對象。
ECMA-262定義了下列7中錯誤類型:
```
Error
EvalError
RangeError
ReferenceError
SyntaxError
TypeError
URIError
```
Error是基類型,其他錯誤類型都繼承自該類型。所有錯誤類型共享了一組相同的屬性。
**(1)EvalError類型**
EvalError類型的錯誤會在使用eval()函數而發生異常時拋出。簡單的說,如果沒有把eval()當成函數調用,就會拋出異常。比如:
```
new eval() // 拋出EvalError
eval = foo; // 拋出EvalError
```
注意:在ES5中已經不在出現了。
**(2)RangeError類型**
RangeError類型的錯誤會在數值超出相應范圍時觸發。主要有幾種情況,一是數組長度為負數,二是Number對象的方法參數超出范圍,以及函數堆棧超過最大值。
```
var item = new Array(-20); // 拋出RangeError異常
```
**(3)ReferenceError類型**
在找不到對象的情況下,會發生ReferenceError。通常,在訪問不存在的變量時,就會發生這種錯誤。
```
var obj = x; // 在x并未聲明的情況下拋出ReferenceError
```
**(4)SyntaxError類型**
SyntaxError是解析代碼時發生的語法錯誤。
```
var 1a; // 變量名錯誤,拋出SyntaxError
```
**(5)TypeError類型**
在變量中保存著意外的類型,或在訪問不存在的方法時,都會導致這種錯誤。
```
var o = new 10; //拋出TypeError
```
**(6)URIError類型**
URIError是URI相關函數的參數不正確時拋出的錯誤,主要涉及encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()這六個函數。
**2.2 拋出錯誤**
與try-catch語句相配的還有一個throw操作符,用于隨時拋出自定義錯誤。拋出錯誤時,必須要給throw操作符指定一個值,這個值可以是任何類型。
```
throw 1;
throw 'tg';
throw true;
throw {name: 'tg'};
```
上面的代碼都是有效的。
在遇到throw操作符時,代碼會立即停止運行。僅當有try-catch語句捕獲到被拋出的值時,代碼才會繼續執行。
**2.3 Error對象**
所有拋出的錯誤都是Error構造函數的實例。Error構造函數接受一個參數,表示錯誤提示,可以從實例的message屬性讀到這個參數。
在JavaScript中,Error對象的實例必須有message屬性,表示出錯時的提示信息。在大多數JavaScript引擎中,Error實例還可能有name和stack屬性,分別表示錯誤的名稱和錯誤的堆棧。
```
var err = new Error('出錯了');
err.message; // "出錯了"
```
**2.4 自定義錯誤**
我們還可以創建自定義錯誤消息,最常用的錯誤類型是Error、RangeError、ReferenceError和TypeError。
```
throw new Error('報錯了');
throw new RangeError('數組長度錯誤');
```
另外,利用原型鏈還可以通過繼承Error來創建自定義錯誤類型:
```
function CustomError(message){
this.name = 'CustomError';
this.message = message;
}
CustomError.prototype = new Error();
throw new CustomError('我的錯誤信息');
```
**3、錯誤(error)事件**
任何沒有通過try-catch處理的錯誤都會觸發window對象的error事件。
onerror事件處理程序不會創建event對象,但它接受三個參數:錯誤消息、錯誤所在的URL和行號。
```
window.onerror = function(message, url, line){
};
```
當你在事件處理程序中返回false,可以阻止瀏覽器報告錯誤的默認行為
```
window.onerror = function(message, url, line){
return false;
};
```
**4、調試技術**
**4.1 alert方法**
在以前,大多數都是在要調試的代碼中插入alert()函數,看是否執行到這一步來判斷哪里出錯,這種方式比較麻煩,因為alert()會阻止后續代碼的執行(除非你關閉了alert彈窗),而且調試后還要清理。
**4.2 console**
隨著瀏覽器的不斷改善,現在的瀏覽器都有JavaScript控制臺,我們可以向這些控制臺輸出消息,比如最常用的console對象,它的常用方法如下:
- error(message):將錯誤消息記錄到控制臺
- info(message):將信息性消息記錄到控制臺
- log(message):將一般消息記錄到控制臺
- warn(message):將警告消息記錄到控制臺
```
function test(){
console.log('結果:' + (1 + 2));
}
```
**4.3 throw**
使用throw拋出錯誤。
- 前言
- JavaScript簡介
- 基本概念
- 語法
- 數據類型
- 運算符
- 表達式
- 語句
- 對象
- 數組
- 函數
- 引用類型(對象)
- Object對象
- Array對象
- Date對象
- RegExp對象
- 基本包裝類型(Boolean、Number、String)
- 單體內置對象(Global、Math)
- console對象
- DOM
- DOM-屬性和CSS
- BOM
- Event 事件
- 正則表達式
- JSON
- AJAX
- 表單和富文本編輯器
- 表單
- 富文本編輯器
- canvas
- 離線應用
- 客戶端存儲(Cookie、Storage、IndexedDB)
- HTML5 API
- Video/Audio
- Geolocation API
- requestAnimationFrame
- File API
- FullScreen API
- IndexedDB
- 檢測設備方向
- Blob
- vibrate
- Luminosity API
- WebRTC
- Page Visibility API
- Performance API
- Web Speech
- Notification
- 面向對象的程序設計
- 概述
- this關鍵字
- 原型鏈
- 作用域
- 常用API合集
- SVG
- 錯誤處理機制
- JavaScript開發技巧合集
- 編程風格
- 垃圾回收機制