摘要:類型的錯(cuò)誤會(huì)在數(shù)值超出相應(yīng)范圍時(shí)觸發(fā)。最常發(fā)生類型錯(cuò)誤的情況,就是傳遞給函數(shù)的參數(shù)事先未經(jīng)檢查,結(jié)果傳入類型與預(yù)期類型不相符。捕獲錯(cuò)誤的目的在于避免瀏覽器以默認(rèn)方式處理它們而拋出錯(cuò)誤的目的在于提供錯(cuò)誤發(fā)生具體原因的消息。
0 前言
目前讀到了《高程3》的錯(cuò)誤檢測(cè)部分,現(xiàn)在先挖一個(gè)坑,關(guān)于錯(cuò)誤檢測(cè)應(yīng)該寫三篇總結(jié):firebug檢測(cè)錯(cuò)誤和輸出信息;try-catch錯(cuò)誤捕獲;常見錯(cuò)誤種類。
本篇邏輯思路如下:首先介紹進(jìn)行錯(cuò)誤捕獲的try-catch語(yǔ)句;然后介紹常見的錯(cuò)誤類型,這點(diǎn)會(huì)結(jié)合firebug來(lái)說(shuō)明;其次介紹try-catch語(yǔ)句和錯(cuò)誤類型結(jié)合使用以捕獲錯(cuò)誤;但是如果捕獲的錯(cuò)誤以瀏覽器的語(yǔ)言表示,還是很難找到錯(cuò)誤,因此推薦使用throw拋出開發(fā)者自定義的錯(cuò)誤,這樣,錯(cuò)誤的位置和原因就會(huì)更易發(fā)現(xiàn);最后就錯(cuò)誤拋出和錯(cuò)誤捕獲進(jìn)行了總結(jié)討論。
1 try-catch簡(jiǎn)介良好的錯(cuò)誤處理機(jī)制可以讓用戶和開發(fā)者及時(shí)得到提醒,知道到底發(fā)生了什么事,因而不會(huì)驚惶失措。ECMA-262 第 3 版引入了 try-catch 語(yǔ)句,作為 JavaScript 中處理異常的一種標(biāo)準(zhǔn)方式。基本的語(yǔ)法如下所示,
try{ // 可能會(huì)導(dǎo)致錯(cuò)誤的代碼 } catch(error){ // 在錯(cuò)誤發(fā)生時(shí)怎么處理 }
我們應(yīng)該把所有可能會(huì)拋出錯(cuò)誤的代碼都放在 try 語(yǔ)句塊中,而把那些用于錯(cuò)誤處理的代碼放在 catch 塊中。如果 try 塊中的任何代碼發(fā)生了錯(cuò)誤,就會(huì)立即退出代碼執(zhí)行過(guò)程,然后接著執(zhí)行 catch 塊。此時(shí), catch 塊會(huì)接收到一個(gè)包含錯(cuò)誤信息的對(duì)象。即使你不想使用這個(gè)錯(cuò)誤對(duì)象,也要指定一個(gè)參數(shù)名。這個(gè)對(duì)象中包含的實(shí)際信息會(huì)因?yàn)g覽器而異,但共同的是有一個(gè)保存著錯(cuò)誤消息的 message 屬性。這個(gè) message 屬性是唯一一個(gè)能夠保證所有瀏覽器都支持的屬性,除此之外, IE、 Firefox、 Safari、 Chrome 以及 Opera 都為錯(cuò)誤對(duì)象添加了其他相關(guān)信息。在跨瀏覽器編程時(shí),最好還是只使用 message 屬性。
一個(gè)測(cè)試?yán)樱?br>
只要代碼中包含 finally 子句,則無(wú)論 try 或 catch 語(yǔ)句塊中包含什么代碼——甚至 return 語(yǔ)句,都不會(huì)阻止 finally 子句的執(zhí)行。如下例所示:
function testFinally() { try { return 2; } catch (error) { return 1; } finally { return 0; } } function testWithoutFinally() { try { return 2; } catch (error) { return 1; } } console.log(testFinally());//輸出0 console.log(testWithoutFinally());//輸出2
如果提供 finally 子句,則 catch 子句就成了可選的(catch 或 finally 有一個(gè)即可)。 IE7 及更早版本中有一個(gè) bug:除非有 catch 子句,否則 finally 中的代碼永遠(yuǎn)不會(huì)執(zhí)行。IE8 修復(fù)了這個(gè) bug。如果你仍然要考慮 IE 的早期版本,那就只好提供一個(gè) catch 子句,哪怕里面什么都不寫。
另一個(gè)測(cè)試實(shí)例:
var example = function() { try { window.someNonexistentFunction(); } catch (error) { console.log(error.name); console.log(error.message); return 1; } finally { console.log("everything is over"); } }; example();
測(cè)試結(jié)果:先后執(zhí)行了try/catch/finally中的語(yǔ)句,問(wèn)題是為什么會(huì)在最后執(zhí)行一次catch中的return語(yǔ)句?留給自己一個(gè)問(wèn)題吧。
每種錯(cuò)誤都有對(duì)應(yīng)的錯(cuò)誤類型,而當(dāng)錯(cuò)誤發(fā)生時(shí),就會(huì)拋出相應(yīng)類型的錯(cuò)誤對(duì)象(error object)。ECMA-262 定義了下列 7 種錯(cuò)誤類型:
1) Error 是基類型,其他錯(cuò)誤類型都繼承自該類型。因此,所有錯(cuò)誤類型共享了一組相同的屬性(錯(cuò)誤對(duì)象中的方法全是默認(rèn)的對(duì)象方法)。
2)EvalError 類型的錯(cuò)誤會(huì)在使用 eval()函數(shù)而發(fā)生異常時(shí)被拋出,但是拋出的錯(cuò)誤不一定是EvalError 類型。如果沒(méi)有把 eval()當(dāng)成函數(shù)調(diào)用,F(xiàn)irefox 4+和 IE8 對(duì)此拋出 TypeError。
3)RangeError 類型的錯(cuò)誤會(huì)在數(shù)值超出相應(yīng)范圍時(shí)觸發(fā)。例如,在定義數(shù)組時(shí),如果指定了數(shù)組不支持的項(xiàng)數(shù)(如-20 或 Number.MAX_VALUE),就會(huì)觸發(fā)這種錯(cuò)誤。
4)在找不到對(duì)象的情況下,會(huì)發(fā)生 ReferenceError(這種情況下,會(huì)直接導(dǎo)致人所共知的"object expected"瀏覽器錯(cuò)誤)。通常,在訪問(wèn)不存在的變量時(shí),就會(huì)發(fā)生這種錯(cuò)誤。
5) 至于 SyntaxError,當(dāng)我們把語(yǔ)法錯(cuò)誤的 JavaScript 字符串傳入 eval()函數(shù)時(shí),就會(huì)導(dǎo)致此類錯(cuò)誤。如果語(yǔ)法錯(cuò)誤的代碼出現(xiàn)在 eval()函數(shù)之外,則不太可能使用 SyntaxError,因?yàn)榇藭r(shí)的語(yǔ)法錯(cuò)誤會(huì)導(dǎo)致 JavaScript 代碼立即停止執(zhí)行。
6)TypeError 類型在 JavaScript 中會(huì)經(jīng)常用到,在變量中保存著意外的類型時(shí),或者在訪問(wèn)不存在的方法時(shí),都會(huì)導(dǎo)致這種錯(cuò)誤。錯(cuò)誤的原因雖然多種多樣,但歸根結(jié)底還是由于在執(zhí)行特定于類型的操作時(shí),變量的類型并不符合要求所致。最常發(fā)生類型錯(cuò)誤的情況,就是傳遞給函數(shù)的參數(shù)事先未經(jīng)檢查,結(jié)果傳入類型與預(yù)期類型不相符。
7) 在使用 encodeURI()或 decodeURI(),而 URI 格式不正確時(shí),就會(huì)導(dǎo)致 URIError 錯(cuò)誤。這種錯(cuò)誤也很少見,因?yàn)榍懊嬲f(shuō)的這兩個(gè)函數(shù)的容錯(cuò)性非常高。
上述測(cè)試過(guò)程在FF如下:
3 使用try-catch語(yǔ)句捕獲錯(cuò)誤要想知道錯(cuò)誤的類型,可以像下面這樣在 try-catch 語(yǔ)句的 catch 語(yǔ)句中使用 instanceof 操作符。
try { someFunction(); } catch (error){ if (error instanceof TypeError){ //處理類型錯(cuò)誤 } else if (error instanceof ReferenceError){ //處理引用錯(cuò)誤 } else { //處理其他類型的錯(cuò)誤 } }
在跨瀏覽器編程中,檢查錯(cuò)誤類型是確定處理方式的最簡(jiǎn)便途徑;而包含在 message 屬性中的錯(cuò)誤消息會(huì)因?yàn)g覽器而異。
使用 try-catch 最適合處理那些我們無(wú)法控制的錯(cuò)誤。假設(shè)你在使用一個(gè)大型 JavaScript 庫(kù)中的函數(shù),該函數(shù)可能會(huì)有意無(wú)意地拋出一些錯(cuò)誤。由于我們不能修改這個(gè)庫(kù)的源代碼,所以大可將對(duì)該函數(shù)的調(diào)用放在 try-catch 語(yǔ)句當(dāng)中,萬(wàn)一有什么錯(cuò)誤發(fā)生,也好恰當(dāng)?shù)靥幚硭鼈儭?/p>
4 throw拋出自定義錯(cuò)誤
與 try-catch 語(yǔ)句相配的還有一個(gè) throw 操作符,用于隨時(shí)拋出自定義錯(cuò)誤。拋出錯(cuò)誤時(shí),必須要給 throw 操作符指定一個(gè)值,這個(gè)值是什么類型,沒(méi)有要求。在遇到 throw 操作符時(shí),代碼會(huì)立即停止執(zhí)行。僅當(dāng)有 try-catch 語(yǔ)句捕獲到被拋出的值時(shí),代碼才會(huì)繼續(xù)執(zhí)行。
通過(guò)使用自定義的內(nèi)置錯(cuò)誤類型,可以更真實(shí)地模擬瀏覽器錯(cuò)誤。每種錯(cuò)誤類型的構(gòu)造函數(shù)接收一個(gè)參數(shù),即實(shí)際的錯(cuò)誤消息。下面是例子。
throw new Error("Something bad happened."); throw new SyntaxError("I don’t like your syntax."); throw new TypeError("What type of variable do you take me for?"); throw new RangeError("Sorry, you just don’t have the range."); throw new EvalError("That doesn’t evaluate."); throw new URIError("Uri, is that you?"); throw new ReferenceError("You didn’t cite your references properly.");
瀏覽器會(huì)像處理自己生成的錯(cuò)誤一樣,來(lái)處理這些代碼拋出的錯(cuò)誤。換句話說(shuō),瀏覽器會(huì)以常規(guī)方式報(bào)告這一錯(cuò)誤,并且會(huì)顯示這里的自定義錯(cuò)誤消息。
拋出自定義錯(cuò)誤的意義:方便快速定位錯(cuò)誤并糾錯(cuò)。雖然瀏覽器會(huì)自己報(bào)錯(cuò),但是這些報(bào)錯(cuò)信息在瀏覽器中達(dá)不到統(tǒng)一,而且如果出現(xiàn)同種類型錯(cuò)誤,查找來(lái)源是復(fù)雜的,尤其是在數(shù)千行代碼中。但是如果你知道可能的代碼錯(cuò)誤,可以直接在代碼中添加這些自定義的錯(cuò)誤,一旦發(fā)生這些錯(cuò)誤,瀏覽器就報(bào)出自定義錯(cuò)誤,關(guān)鍵是這個(gè)錯(cuò)誤的位置和類型顯而易見。
實(shí)例:一個(gè)必須接收數(shù)組作為參數(shù)的函數(shù)如果接收字符串作為參數(shù)就會(huì)報(bào)錯(cuò)。
function process(values){ values.sort(); for (var i=0, len=values.length; i < len; i++){ if (values[i] > 100){ return values[i]; } } return -1; } var a = process("string"); console.log(a);
firebug中結(jié)果:
添加自定義錯(cuò)誤后的代碼:
function process(values){ if (!(values instanceof Array)){ throw new Error("process(): Argument must be an array."); } values.sort(); for (var i=0, len=values.length; i < len; i++){ if (values[i] > 100){ return values[i]; } } return -1; } var a = process("string"); console.log(a);
firebug中結(jié)果:
如果 values 參數(shù)不是數(shù)組,就會(huì)拋出一個(gè)錯(cuò)誤。錯(cuò)誤消息中包含了函數(shù)的名稱,以及為什么會(huì)發(fā)生錯(cuò)誤的明確描述。如果一個(gè)復(fù)雜的 Web 應(yīng)用程序發(fā)生了這個(gè)錯(cuò)誤,那么查找問(wèn)題的根源也就容易多了。
利用原型鏈還可以通過(guò)繼承 Error 來(lái)創(chuàng)建自定義錯(cuò)誤類型。此時(shí),需要為新創(chuàng)建的錯(cuò)誤類型指定 name 和 message 屬性。
一個(gè)實(shí)例:
//通過(guò)繼承Error實(shí)現(xiàn)自定義錯(cuò)誤類型,要定義name和message屬性 function CustomError(message){ this.name = "CustomError"; this.message = message; } CustomError.prototype = new Error(); function process(values){ //如果出現(xiàn)錯(cuò)誤,就拋出自定義錯(cuò)誤類型的對(duì)象實(shí)例 if (!(values instanceof Array)){ throw new CustomError("process(): Argument must be an array."); } values.sort(); for (var i=0, len=values.length; i < len; i++){ if (values[i] > 100){ return values[i]; } } return -1; } process("string");
firebug顯示自定義類型的錯(cuò)誤:
5 拋出錯(cuò)誤與使用 try-catch捕獲錯(cuò)誤關(guān)于何時(shí)該拋出錯(cuò)誤,而何時(shí)該使用 try-catch 來(lái)捕獲它們,是一個(gè)老生常談的問(wèn)題。一般來(lái)說(shuō),應(yīng)用程序架構(gòu)的較低層次中經(jīng)常會(huì)拋出錯(cuò)誤,但這個(gè)層次并不會(huì)影響當(dāng)前執(zhí)行的代碼,因而錯(cuò)誤通常得不到真正的處理。如果你打算編寫一個(gè)要在很多應(yīng)用程序中使用的 JavaScript 庫(kù),甚至只編寫一個(gè)可能會(huì)在應(yīng)用程序內(nèi)部多個(gè)地方使用的輔助函數(shù),我都強(qiáng)烈建議你在拋出錯(cuò)誤時(shí)提供詳盡的信息。然后,即可在應(yīng)用程序中捕獲并適當(dāng)?shù)靥幚磉@些錯(cuò)誤。
說(shuō)到拋出錯(cuò)誤與捕獲錯(cuò)誤,我們認(rèn)為只應(yīng)該捕獲那些你確切地知道該如何處理的錯(cuò)誤。捕獲錯(cuò)誤的目的在于避免瀏覽器以默認(rèn)方式處理它們;而拋出錯(cuò)誤的目的在于提供錯(cuò)誤發(fā)生具體原因的消息。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/87976.html
摘要:類型的錯(cuò)誤會(huì)在數(shù)值超出相應(yīng)范圍時(shí)觸發(fā)。最常發(fā)生類型錯(cuò)誤的情況,就是傳遞給函數(shù)的參數(shù)事先未經(jīng)檢查,結(jié)果傳入類型與預(yù)期類型不相符。捕獲錯(cuò)誤的目的在于避免瀏覽器以默認(rèn)方式處理它們而拋出錯(cuò)誤的目的在于提供錯(cuò)誤發(fā)生具體原因的消息。 0 前言 目前讀到了《高程3》的錯(cuò)誤檢測(cè)部分,現(xiàn)在先挖一個(gè)坑,關(guān)于錯(cuò)誤檢測(cè)應(yīng)該寫三篇總結(jié):firebug檢測(cè)錯(cuò)誤和輸出信息;try-catch錯(cuò)誤捕獲;常見錯(cuò)誤種類。...
錯(cuò)誤處理與調(diào)試 錯(cuò)誤處理 try-catch語(yǔ)句 try{ //可能會(huì)導(dǎo)致錯(cuò)誤的代碼 }catch(error){ //在錯(cuò)誤發(fā)生時(shí)怎么處理 } 發(fā)生錯(cuò)誤時(shí)可以顯示瀏覽器給出的信息 try{ window.someNonexistentFunction(); }catch(error){ alert(error.message); } 在try-catch語(yǔ)句中是可選的,但...
摘要:不允許直接訪問(wèn)內(nèi)存中的位置,也就是說(shuō)不能直接操作對(duì)象的內(nèi)存空間。在操作對(duì)象時(shí),實(shí)際上是在操作對(duì)象的引用而不是實(shí)際的對(duì)象。解除引用的真正作用是讓值脫離執(zhí)行環(huán)境,以便垃圾收集器下次運(yùn)行時(shí)將其回收 1 基本類型和引用類型的值 基本數(shù)據(jù)類型是按值訪問(wèn)的,因?yàn)榭梢圆僮鞅4嬖谧兞恐械膶?shí)際的值 基本類型值在內(nèi)存中占據(jù)固定大小的空間,因此被保存在棧內(nèi)存中 引用類型的值是保存在內(nèi)存中的對(duì)象。JavaSc...
摘要:使用函數(shù)發(fā)生異常時(shí)拋出。數(shù)值超出相應(yīng)范圍時(shí)拋出。拋出錯(cuò)誤與相配的還有一個(gè)操作符,用于拋出自定義錯(cuò)誤。錯(cuò)誤事件沒(méi)有通過(guò)處理的錯(cuò)誤都會(huì)觸發(fā)對(duì)象的事件。任何瀏覽器中,事件處理程序都不會(huì)創(chuàng)建對(duì)象,但它可以接受個(gè)參數(shù)錯(cuò)誤消息錯(cuò)誤所在的和行號(hào)。 try-catch語(yǔ)句 該語(yǔ)句最適合處理那些我們無(wú)法控制的錯(cuò)誤,在明明白白地知道自己的代碼會(huì)發(fā)生錯(cuò)誤時(shí),再使用該語(yǔ)句就不太合適了。 ECMA-262第3...
摘要:標(biāo)識(shí)符按以下規(guī)則組合第一個(gè)字符必須是一個(gè)字母,下劃線或一個(gè)美元符號(hào)。包含值的變量和尚未定義的變量是不一樣的,例子報(bào)錯(cuò)然而,對(duì)未初始化的變量執(zhí)行操作符會(huì)返回值,對(duì)未聲明的變量執(zhí)行操作符統(tǒng)一也會(huì)返回值。 1. 語(yǔ)法 1.1 區(qū)分大小寫 變量、函數(shù)名和操作費(fèi)都區(qū)分大小寫。 1.2 標(biāo)識(shí)符 標(biāo)識(shí)符指變量、函數(shù)、屬性的名字,或者函數(shù)的參數(shù)。標(biāo)識(shí)符按以下規(guī)則組合: 第一個(gè)字符必須是一個(gè)字母,下劃線...
閱讀 454·2019-08-29 12:44
閱讀 3035·2019-08-26 17:49
閱讀 2489·2019-08-26 13:40
閱讀 1202·2019-08-26 13:39
閱讀 3684·2019-08-26 11:59
閱讀 1846·2019-08-26 10:59
閱讀 2490·2019-08-23 18:33
閱讀 2718·2019-08-23 18:30