錯誤類型: 執行代碼期間可能會發生的錯誤有多種類型。每種錯誤都有對應的錯誤類型,而當錯誤發生時,就會拋出相應類型的錯誤對象。
ECMA-262定義的7種錯誤類型
- Error: 是錯誤的基類型,其他錯誤類型都繼承該類型。Error 類型的錯誤很少見,如果有也是瀏覽器拋出的。
- EvalError: 使用eval() 函數而發生異常時被拋出。
- RangeError:在數值超過相應范圍是就會被拋出。
- ReferenceError: 在找不到對象的情況下,會發生 ReferenceEroor 。通常,在訪問不存在的變量時,就會發生這種錯誤。
- SyntaxError: 語法錯誤時會拋出此異常。
- TypeError: 在變量中保存著意外的類型時,或者訪問不存在的方法時,都會導致這種錯誤。錯誤的原因雖然多種多樣,但歸根結底還是由于在執行特定于類型的操作時,變量的類型并不符合要求所致。
- URIError: 在使用 encodeURI() 或 decodeURI(),而URI格式不正確,就會導致URIError錯誤。
@Example:
<script type="text/javascript" charset="utf-8">//1、 數值超過范圍時拋出 RangeErrorvar item1 = new Array(-10); //拋出 RangeError: invalid array lengthvar item1 = new Array(Number.MAX_VALUE); //拋出 RangeError: invalid array length//2、找不到對象時會拋出 ReferenceErrorvar obj = x; // 在x并未聲明的情況下拋出 ReferenceError: x is not defined//3、語法錯誤是拋出 SyntaxErrorvar sum = 1++2; //SyntaxError: invalid increment operand//4、在變量中保存著意外的類型時,或者訪問不存在的方法時,都會導致 TypeError 錯誤var obj = new 10(); //拋出 TypeError: 10 is not a constructorif("name" in true){} //拋出 TypeError: invalid 'in' operand trueFunction.prototype.toString.call("name"); //拋出 TypeError: Function.prototype.toString called on incompatible object//5、在使用 encodeURI() 或 decodeURI(),而URI格式不正確,就會導致URIError錯誤。這種錯誤也很少見,因為這兩個函數的容錯性非常高。
</script>
異常的 try-catch 處理
使用 try-catch 最適合處理那些我們無法控制的錯誤。假設你在使用一個大型的 JavaScript 庫中的函數,該函數可能會有意無意地拋出一些錯誤。由于我們不能修改這個庫的源代碼,所以大可將對該函數的調用放在 try-catch 語句當中,萬一有什么錯誤發生也好恰當的處理它們。如果事前就知道自己的代碼會某種情況下發生錯誤時,再使用 try-chtch 語句就不太合適了。
例如,如果傳遞給函數的參數是字符串而非數值,就會造成函數出錯,那么就應該先檢查參數的類型,然后再決定如何去做。在這種情況下,不應該使用 try-catch 語句。
@Example 1:
<script type="text/javascript" charset="utf-8">try{//do something}catch(error){// error 是發生錯誤時catch塊接受到包含錯誤信息的對象。這個對象包含的實際信息因為瀏覽器而異,但共同的是有一個保存著錯誤消息的message屬性和保存錯誤類型的name屬性。console.log("錯誤消息:"+error.message);console.log("錯誤類型:"+error.name);if(error instanceof TypeError){// 處理類型錯誤}else if(error instanceof ReferenceError){// 處理引用錯誤}else{// 處理其他類型的錯誤}}
</script>
@Example 2:
<script type="text/javascript" charset="utf-8">/*** try-catch-finally: try-catch 語句是可選的,如果try塊中沒有出現錯誤就不會執行 catch 塊語句,但finally 子句中的代碼無論如何都會執行(瀏覽器突然關掉或停電無法工作就另當別論啦)。*/function test1(){try{console.log("執行test1() try塊語句。。。");return 0;}catch(error){console.log("執行test1() catch塊語句。。。");return 1;}finally{console.log("執行test1() finally塊語句。。。");return 520;}}var t1 = test1();console.log("t1: "+t1);function test2(){try{console.log("執行test2() try塊語句。。。");//拋出錯誤讓代碼走 catch 塊throw new Error("測試try-catch-finally.");}catch(error){console.log("執行test2() catch塊語句。。。");return 1;}finally{console.log("執行test2() finally塊語句。。。");return 1314;}}var t2 = test2();console.log("t2: "+t2);function test3(){try{return 1314520;}catch(error){console.log("執行test3() catch塊語句。。。");return 1;}finally{console.log("執行test3() finally塊語句。。。");}}var t3 = test3();console.log("t3: "+t3);/********************* 【開始】運行結果 ********************執行test1() try塊語句。。。執行test1() finally塊語句。。。t1: 520執行test2() try塊語句。。。執行test2() catch塊語句。。。執行test2() finally塊語句。。。t2: 1314執行test3() finally塊語句。。。t3: 1314520********************* 【結束】運行結果 ********************/ /*** 總結:* 代碼中包含finally子句,那么無論try還是catch語句塊中的return語句都將不會影響到finally子句的執行。因此在使用finally子句之前,* 一定要非常清楚的知道想讓代碼怎么樣。*/
</script>
@Example 3:
<script type="text/javascript" charset="utf-8">/*** 拋出錯誤* * 語法格式:throw 錯誤值(錯誤值的類型沒有要求);* @example:* throw 12345;* throw "Hello Javascript!";* throw true;* throw {name:"Javascript"};* throw new Error("Something bad happened.");* * 在遇到throw操作符時,代碼會立即停止執行。僅當有try-catch語句捕獲到被拋出的值是,代碼才會繼續執行。*//*** 拋出自定義錯誤* * 方式一: 使用錯誤類型拋出自定義錯誤消息的通用錯誤。* @example * throw new Error("Something bad happened.");* throw new SyntaxError("I don't like your syntax style.");* throw new RangeError("Sorry,you just don't hava the range.");* ...* * 以上例子中拋出都是通用錯誤,帶有一條自定義錯誤消息。瀏覽器會像處理自己生成的錯誤一樣,來處理代碼拋出的錯誤。* 換句話說,瀏覽器會以常規方式報告錯誤,并且會顯示這里的自定義錯誤消息。* * * 方式二:利用原型鏈通過繼承Error來創建自定義錯誤類型,此時,需要為新創建的錯誤類型指定name 和 message 屬性。* @example* * function CustomerError(message){* this.name = "CustomerError";* this.message = message;* }* CustomerError.prototype = new Error();* throw new CustomerError("My error message");*//* * @note* IE只有在拋出Error對象的時候才會顯示自定義錯誤消息。對于其他類型,它都無一例外地顯示“exception thrown and not caught”(拋出了異常,并且未被捕獲)*//*** 拋出錯誤的時機* 函數為什么會執行失敗給出更多信息,拋出自定義錯誤是一種很方便的方式。雖說瀏覽器在執行失敗會回給出相應的錯誤但都不是特別明顯,* 而且不同的瀏覽器給出的錯誤消息都不盡相同。* * 例如下面的precess函數:* 如果執行函數是傳給它一個字符串參數,那么sort()的調用就會失敗。對此,不同的瀏覽器會給出不同的錯誤消息,但都不是特別明確。如下:* IE:對象不支持“sort”屬性或方法。* Firefox: values.sort()不是函數。* Chrome: 對象名沒有方法 ‘sort’.* ...*/function process(values){values.sort();for(var i=0,len=values.length;i<len;i++){console.log(values[i]+" , ");}}/*** 優化 process函數:在可能出現錯誤的地方做有效性檢查,在出現錯誤時給出自定義的錯誤信息。* * 好處:重寫后的這個函數,如果values參數不是數組,就會拋出一個錯誤。錯誤消息中包含了函數的名稱,以及為什么會發生錯誤的明確描述。* 如果是一個復雜的web應用程序發生了這個錯誤,那么查找問題的根源就容易多啦。良好的錯誤處理機制應該可以確保代碼中只發生自己拋出的錯誤。*/function process1(values){if(!(values instanceof Array)){throw new Error("process1(): Argument must be an array.");}values.sort();for(var i=0,len=values.length;i<len;i++){console.log(values[i]+" , ");}}/*** 總結:拋出錯誤和捕獲錯誤,我們認為值應該捕獲那些確切知道該如何處理的錯誤。捕獲錯誤的目的在于避免流量器以默認的方式處理它們;* 而拋出錯誤的目的在于提供錯誤發生具體原因的消息。*/
</script>