JavaScript 高級(jí)程序設(shè)計(jì)(第17章 錯(cuò)誤處理與調(diào)試)

第17章 錯(cuò)誤處理與調(diào)試

1. 瀏覽器報(bào)告的錯(cuò)誤

2. 錯(cuò)誤處理

(1) try-catch語(yǔ)句

try {
    window.someNonexistentFunction();
} catch (error){
    alert(error.message);
}
*finally 子句

只要代碼中包含 finally 子句,則無(wú)論 try 或 catch 語(yǔ)句塊中包
含什么代碼——甚至 return 語(yǔ)句,都不會(huì)阻止 finally 子句的執(zhí)行。

*錯(cuò)誤類型
  1. Error是基類型,其他錯(cuò)誤類型都繼承自該類型。
  2. EvalError 類型的錯(cuò)誤會(huì)在使用 eval()函數(shù)而發(fā)生異常時(shí)被拋出。
  3. RangeError 類型的錯(cuò)誤會(huì)在數(shù)值超出相應(yīng)范圍時(shí)觸發(fā)。
  4. ReferenceError類型找不到對(duì)象的情況下拋出。
    5.syntaxError,當(dāng)我們把語(yǔ)法錯(cuò)誤的 JavaScript 字符串傳入 eval()函數(shù)時(shí),就會(huì)導(dǎo)致此類錯(cuò)誤。
  5. TypeError 類型在 JavaScript 中會(huì)經(jīng)常用到,在變量中保存著意外的類型時(shí),或者在訪問(wèn)不存在的 方法時(shí),都會(huì)導(dǎo)致這種錯(cuò)誤。錯(cuò)誤的原因雖然多種多樣,但歸根結(jié)底還是由于在執(zhí)行特定于類型的操作 時(shí),變量的類型并不符合要求所致。
    7.URIError在使用 encodeURI()或 decodeURI(),而 URI 格式不正確時(shí),就會(huì)導(dǎo)致 URIError 錯(cuò)誤。

(2) 拋出錯(cuò)誤

  1. 與 try-catch 語(yǔ)句相配的還有一個(gè)throw 操作符,用于隨時(shí)拋出自定義錯(cuò)誤。拋出錯(cuò)誤時(shí),必須要給 throw 操作符指定一個(gè)值,這個(gè)值是什么類型,沒(méi)有要求。
  2. 在遇到 throw 操作符時(shí),代碼會(huì)立即停止執(zhí)行。僅當(dāng)有 try-catch 語(yǔ)句捕獲到被拋出的值時(shí),代 碼才會(huì)繼續(xù)執(zhí)行
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.");
  1. 利用原型鏈還可以通過(guò)繼承 Error 來(lái)創(chuàng)建自定義錯(cuò)誤類型。
function CustomError(message){
        this.name = "CustomError";
        this.message = message;
}
CustomError.prototype = new Error();
throw new CustomError("My message");

*拋出錯(cuò)誤的時(shí)機(jī)

應(yīng)該在出現(xiàn)某 種特定的已知錯(cuò)誤條件,導(dǎo)致函數(shù)無(wú)法正常執(zhí)行時(shí)拋出錯(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;
 }

(3) 錯(cuò)誤(error)事件

任何沒(méi)有通過(guò) try-catch 處理的錯(cuò)誤都會(huì)觸發(fā) window 對(duì)象的 error 事件。
1.在任何 Web 瀏覽器中,onerror 事件處理程序都不會(huì)創(chuàng)建 event 對(duì)象, 但它可以接收三個(gè)參數(shù):錯(cuò)誤消息、錯(cuò)誤所在的 URL 和行號(hào)。
2.要指定 onerror 事件處理程序,必須使用如下所示的DOM0 級(jí)技術(shù),它沒(méi)有遵循“DOM2 級(jí) 事件”的標(biāo)準(zhǔn)格式。

  1. 在事件處理程序中返回 false,可以阻止瀏覽器報(bào)告錯(cuò)誤的默認(rèn)行為。
window.onerror = function(message, url, line){
    alert(message);
    return false;
};
  1. 圖像也支持 error 事件。只要圖像的 src 特性中的 URL 不能返回可以被識(shí)別的圖像格式,就會(huì)觸 發(fā) error 事件。
var image = new Image();
EventUtil.addHandler(image, "load", function(event){
    alert("Image loaded!");
});
EventUtil.addHandler(image, "error", function(event){
    alert("Image not loaded!");
});
image.src = "smilex.gif"; //指定不存在的文件

(4) 處理錯(cuò)誤的策略

(5) 常見(jiàn)的錯(cuò)誤類型

*類型轉(zhuǎn)換錯(cuò)誤
  1. 類型轉(zhuǎn)換錯(cuò)誤發(fā)生在使用某個(gè)操作符,或者使用其他可能會(huì)自動(dòng)轉(zhuǎn)換值的數(shù)據(jù)類型的語(yǔ)言結(jié)構(gòu)時(shí)。
    在使用相等(==)和不相等(!=)操作符,或者在 if、for 及 while 等流控制語(yǔ)句中使用非布爾值時(shí), 最常發(fā)生類型轉(zhuǎn)換錯(cuò)誤。
*數(shù)據(jù)類型錯(cuò)誤
*通信錯(cuò)誤
  1. 第一種通信錯(cuò)誤與格式不正確的 URL 或發(fā)送的數(shù)據(jù)有關(guān)。最常見(jiàn)的問(wèn)題是在將數(shù)據(jù)發(fā)送給服務(wù)器 之前,沒(méi)有使用 encodeURIComponent()對(duì)數(shù)據(jù)進(jìn)行編碼。

(6) 區(qū)分致命錯(cuò)誤和非致命錯(cuò)誤

  1. 非致命錯(cuò)誤:
  • 不影響用戶的主要任務(wù);
  • 只影響頁(yè)面的一部分;
  • 可以恢復(fù);
  • 重復(fù)相同操作可以消除錯(cuò)誤。
  1. 致命錯(cuò)誤:
  • 應(yīng)用程序根本無(wú)法繼續(xù)運(yùn)行;
  • 錯(cuò)誤明顯影響到了用戶的主要操作;
  • 會(huì)導(dǎo)致其他連帶錯(cuò)誤。

(7) 把錯(cuò)誤記錄到服務(wù)器

3. 調(diào)試技術(shù)

(1) 將消息記錄到控制臺(tái)

  1. 通過(guò) console 對(duì)象向 JavaScript 控制臺(tái)中寫(xiě)入消息,這個(gè)對(duì)象具有下列方法:
  1. error(message):將錯(cuò)誤消息記錄到控制臺(tái)
  2. info(message):將信息性消息記錄到控制臺(tái)
  3. log(message):將一般消息記錄到控制臺(tái)
  4. warn(message):將警告消息記錄到控制臺(tái)
  1. 通過(guò) opera.postError()方法來(lái)訪問(wèn)。這個(gè)方法 接受一個(gè)參數(shù),即要寫(xiě)入到控制臺(tái)中的參數(shù)。
  2. 在 JavaScript 中運(yùn)行 Java 代碼。
function log(message){
         if (typeof console == "object"){
             console.log(message);
         } else if (typeof opera == "object"){
             opera.postError(message);
         } else if (typeof java == "object" && typeof java.lang == "object"){
        java.lang.System.out.println(message);
    }
}

function sum(num1, num2){
        log("Entering sum(), arguments are " + num1 + "," + num2);
    log("Before calculation");
    var result = num1 + num2;
    log("After calculation");
    log("Exiting sum()");
    return result;
}

(2) 將消息記錄到當(dāng)前頁(yè)面

在頁(yè)面中開(kāi)辟一小塊區(qū)域,用以顯示消息。這個(gè)區(qū)域通常是一個(gè) 元素,而該元素可以總是出現(xiàn)在頁(yè)面中,但僅用于調(diào)試目的;也可以是一個(gè)根據(jù)需要?jiǎng)討B(tài)創(chuàng)建的元素。

function log(message){
    var console = document.getElementById("debuginfo");
    if (console === null){
        console = document.createElement("div");
        console.id = "debuginfo";
        console.style.background = "#dedede";
        console.style.border = "1px solid silver";
        console.style.padding = "5px";
        console.style.width = "400px";
        console.style.position = "absolute";
        console.style.right = "0px";
        console.style.top = "0px";
        document.body.appendChild(console);
  }
  console.innerHTML += "<p>" + message + "</p>";
}

(3) 拋出錯(cuò)誤

對(duì)于大型應(yīng)用程序來(lái)說(shuō),自定義的錯(cuò)誤通常都使用 assert()函數(shù)拋出。這個(gè)函數(shù)接受兩個(gè)參數(shù), 一個(gè)是求值結(jié)果應(yīng)該為 true 的條件,另一個(gè)是條件為 false 時(shí)要拋出的錯(cuò)誤。

function assert(condition, message){
    if (!condition){
        throw new Error(message);
    }
}

function divide(num1, num2){
    assert(typeof num1 == "number" && typeof num2 == "number",
           "divide(): Both arguments must be numbers.");
    return num1 / num2;
}

4.常見(jiàn)的 IE 錯(cuò)誤

(1) 操作終止

操作終止: 在修改尚未加載完成的頁(yè)面時(shí),就會(huì)發(fā)生操作終止錯(cuò)誤。發(fā)生錯(cuò)誤時(shí), 會(huì)出現(xiàn)一個(gè)模態(tài)對(duì)話框,告訴你“操作終止?!眴螕舸_定(OK)按鈕,則卸載整個(gè)頁(yè)面,繼而顯示一張 空白屏幕。

當(dāng)<script>節(jié)點(diǎn)被包含在某個(gè)元素中, 而且 JavaScript 代碼又要使用 appendChild()、innerHTML 或其他 DOM 方法修改該元素的父元素或 祖先元素時(shí),將會(huì)發(fā)生操作終止錯(cuò)誤(因?yàn)橹荒苄薷囊呀?jīng)加載完畢的元素)。

(2) 無(wú)效字符

所謂無(wú)效字符,就是 JavaScript 語(yǔ)法中未定義的字符。

(3) 未找到成員

如果在對(duì)象被銷毀之后,又給該對(duì)象賦值,就會(huì)導(dǎo)致未找到成員錯(cuò)誤。而導(dǎo)致這個(gè)錯(cuò)誤 的,一定是 COM 對(duì)象。發(fā)生這個(gè)錯(cuò)誤的最常見(jiàn)情形是使用 event 對(duì)象的時(shí)候。IE 中的 event 對(duì)象是 window 的屬性,該對(duì)象在事件發(fā)生時(shí)創(chuàng)建,在最后一個(gè)事件處理程序執(zhí)行完畢后銷毀。假設(shè)你在一個(gè) 閉包中使用了 event 對(duì)象,而該閉包不會(huì)立即執(zhí)行,那么在將來(lái)調(diào)用它并給 event 的屬性賦值時(shí),就 會(huì)導(dǎo)致未找到成員錯(cuò)誤。

(4) 未知運(yùn)行時(shí)錯(cuò)誤

當(dāng)使用 innerHTML 或 outerHTML 以下列方式指定 HTML 時(shí),就會(huì)發(fā)生未知運(yùn)行時(shí)錯(cuò)誤(Unknown runtime error):一是把塊元素插入到行內(nèi)元素時(shí),二是訪問(wèn)表格任意部分(<table>、<tbody>等)的 任意屬性時(shí)。

(5) 語(yǔ)法錯(cuò)誤

如果你引用了外部的 JavaScript 文件,而該文件最終并沒(méi)有返回 JavaScript 代碼,IE 也會(huì)拋出語(yǔ)法 錯(cuò)誤。例如,<script>元素的 src 特性指向了一個(gè) HTML 文件,就會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤。

(6) 系統(tǒng)無(wú)法找到指定資源

在使用 JavaScript 請(qǐng)求某個(gè)資源 URL,而該 URL 的長(zhǎng)度超過(guò)了 IE 對(duì) URL 最長(zhǎng)不能超過(guò) 2083 個(gè)字符的限制時(shí),就會(huì)發(fā)生這個(gè)錯(cuò)誤。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容