1. 程式人生 > >JavaScript筆記:錯誤處理與除錯

JavaScript筆記:錯誤處理與除錯

1、瀏覽器報告的錯誤

IE

IE 是唯一一個在瀏覽器的介面窗體(chrome)中顯示 JavaScript 錯誤資訊的瀏覽器。在發生 JavaScript 錯誤時,瀏覽器左下角會出現一個黃色的圖示,圖示旁邊則顯示著”Error on page”(頁面中有錯誤)。 假如不是存心去看的話,你很可能不會注意這個圖示。雙擊這個圖示,就會看到一個包含錯誤訊息的對話方塊,其中還包含諸如行號、字元數、錯誤程式碼及檔名(其實就是你在檢視的頁面的 URL)等相關資訊。

Firefox

預設情況下,Firefox 在 JavaScript 發生錯誤時不會通過瀏覽器介面給出提示。但它會在後臺將錯誤記錄到錯誤控制檯中。單擊“Tools”(工具)選單中的“Error Console”(錯誤控制檯)可以顯示錯誤控制檯。你會發現,錯誤控制檯中實際上還包含與 JavaScript、CSS 和 HTML 相關的警告和資訊,可以通過篩選找到錯誤。

目前,最流行的 Firefox 外掛 Firebug,已經成為開發人員必備的 JavaScript 糾錯工具。這個可以從 www.getfirebug.com 下載到的外掛,會在 Firefox 狀態列的右下角區域新增一個圖示。預設情況下,右下 角區域顯示的是一個綠色對勾圖示。在有 JavaScript 錯誤發生時,圖示會變成紅叉,同時旁邊顯示錯誤 的數量。單擊這個紅叉會開啟 Firebug 控制檯,其中顯示有錯誤訊息、錯誤所在的程式碼行(不包含上下 文)、錯誤所在的 URL 以及行號。

Safari

Windows 和 Mac OS 平臺的 Safari 在預設情況下都會隱藏全部 JavaScript 錯誤。為了訪問到這些資訊,必須啟用“Develop”(開發)選單。為此,需要單擊“Preferences”(偏好設定),然後在“Advanced”(高階)選項卡中,選中“Show develop menu in menubar”(在選單欄中 顯示“開發”選單)。啟用此項設定之後,就會在 Safari 的選單欄中看到一個“Develop”選單。

“Develop”選單中提供了一些與除錯有關的選項,還有一些選項可以影響當前載入的頁面。單擊 “Show Error Console”(顯示錯誤控制檯)選項,將會看到一組 JavaScript 及其他錯誤。控制檯中顯示著錯誤訊息、錯誤的 URL 及錯誤的行號。 單擊控制檯中的錯誤訊息,就可以開啟導致錯誤的原始碼。除了被輸出到控制檯之外,JavaScript錯誤不會影響 Safari 視窗的外觀。

Opera

Opera 在預設情況下也會隱藏 JavaScript 錯誤,所有錯誤都會被記錄到錯誤控制檯中。要開啟錯誤 控制檯,需要單擊“Tools”(工具)選單,在“Advanced”(高階)子選單項下面再單擊“Error Console”(錯誤控制檯)。與 Firefox 一樣,Opera 的錯誤控制檯中也包含了除 JavaScript 錯誤之外的很多來源(如 HTML、CSS、XML、XSLT 等)的錯誤和警告資訊。要分類檢視不同來源的訊息,可以使用左下角的下拉選擇框。

錯誤訊息中顯示著導致錯誤的 URL 和錯誤所在的執行緒。有時候,還會有棧跟蹤資訊。除了錯誤控制檯中顯示的資訊之外,沒有其他途徑可以獲得更多資訊。也可以讓 Opera 一發生錯誤就彈出錯誤控制檯。為此,要在“Tools”(工具)選單中單擊“Preferences” (首選項),再單擊“Advanced”(高階)選項卡,然後從左側選單中選擇“Content”(內容)。單擊“JavaScrip Options”(JavaScript 選項)按鈕,顯示選項對話方塊。 在這個選項對話方塊中,選中“Open console on error”(出錯時開啟控制檯),單擊“OK”(確定)按鈕。這樣,每當發生 JavaScript 錯誤時,就會彈出錯誤控制檯。另外,還可以針對特定的站點來作此設定,方法是單擊“Tools”(工具)、“Quick Preferences”(快速引數)、“Edit Site Preferences”(編輯站點首選項),選擇“Scripting”(指令碼)選項卡,最後選中“Open console on error”(出錯時開啟 控制檯)。

Chrome

與 Safari 和 Opera 一樣,Chrome 在預設情況下也會隱藏 JavaScript 錯誤。所有錯誤都將被記錄到 Web Inspector 控制檯中。要檢視錯誤訊息,必須開啟 Web Inspector。為此,要單擊位於位址列右側的 “Control this page”(控制當前頁)按鈕,選擇“Developer”(開發人員)、“JavaScript console”(JavaScript控制檯)。

開啟的 Web Inspector 中包含著有關頁面的資訊和 JavaScript 控制檯。控制檯中顯示著錯誤訊息、錯誤的 URL 和錯誤的行號。

單擊 JavaScript 控制檯中的錯誤,就可以定位到導致錯誤的原始碼行。

2、錯誤處理

(諄諄教誨ing)
雖然客戶端應用程式的錯誤處理很重要,但真正受到重視,還是最近幾年的事。實際上,我們 要面對這樣一個不爭的事實:使用 Web 的絕大多數人都不是技術高手,其中甚至有很多人根本就不明白瀏覽器到底是什麼,更不用說讓他們說喜歡哪一個了。本章前面討論過,每個瀏覽器在發生 JavaScript 錯誤時的行為都或多或少有一些差異。有的會顯示小圖示,有的則什麼動靜也沒有,瀏覽器對 JavaScript 錯誤的這些預設行為對終端使用者而言,毫無規律可循。最理想的情況下,使用者遇到錯誤搞不清為什麼,他們會再試著重做一次;最糟糕的情況下,使用者會惱羞成怒,一去不復返了。良好的錯誤處理機制可以 讓使用者及時得到提醒,知道到底發生了什麼事,因而不會驚惶失措。為此,作為開發人員,我們必須理解在處理 JavaScript 錯誤的時候,都有哪些手段和工具可以利用。

try-catch語句

ECMA-262 第 3 版引入了 try-catch 語句,作為 JavaScript 中處理異常的一種標準方式。基本的語法如下所示:

try{
    // 可能會導致錯誤的程式碼 
} catch(error){
    // 在錯誤發生時怎麼處理 
}

如果 try 塊中的任何程式碼發生了錯誤,就會立即退出程式碼執行過程,然後接著執行 catch 塊。此時,catch 塊會接收到一個包含錯誤資訊的物件。與在其他語言中不同的是,即使你不想使用這個錯誤物件,也要給它起個名字。這個物件中包含的實際資訊會因瀏覽器而異,但共同的是有一個儲存著錯誤訊息的 message 屬性。ECMA-262 還規定了一個儲存錯誤型別的 name 屬性;當前所有瀏覽器都支援這個屬性(Opera 9 之前的版本不支援這個屬性)。因此,在發生錯誤時,就可以像下面這樣實事求是地顯 示瀏覽器給出的訊息:

try {
    window.someNonexistentFunction();
} catch (error){
    alert(error.message);
}

這個例子在向用戶顯示錯誤訊息時,使用了錯誤物件的message屬性。這個message屬性是唯一 一個能夠保證所有瀏覽器都支援的屬性。

finally 子句:

雖然在 try-catch 語句中是可選的,但 finally 子句一經使用,其程式碼無論如何都會執行。換句話說,try 語句塊中的程式碼全部正常執行,finally 子句會執行;如果因為出錯而執行了 catch 語句塊,finally 子句照樣還會執行。只要程式碼中包含 finally 子句,則無論 try 或 catch 語句塊中包含什麼程式碼——甚至 return 語句,都不會阻止 finally 子句的執行。

function testFinally(){
        try {
            return 2;
        } catch (error){
            return 1;
        } finally {
            return 0; 
        }
}

這個函式在 try-catch 語句的每一部分都放了一條 return 語句。表面上看,呼叫這個函式會返回 2,因為返回 2 的 return 語句位於 try 語句塊中,而執行該語句又不會出錯。可是,由於最後還有 一個 finally 子句,結果就會導致該 return 語句被忽略;也就是說,呼叫這個函式只能返回 0。如果把 finally 子句拿掉,這個函式將返回 2。

錯誤型別:

執行程式碼期間可能會發生的錯誤有多種型別。每種錯誤都有對應的錯誤型別,而當錯誤發生時,就會丟擲相應型別的錯誤物件。ECMA-262 定義了下列 7 種錯誤型別:
Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError。

其中,Error 是基型別,其他錯誤型別都繼承自該型別。因此,所有錯誤型別共享了一組相同的屬性(錯誤物件中的方法全是預設的物件方法)。Error 型別的錯誤很少見,如果有也是瀏覽器丟擲的;這個基型別的主要目的是供開發人員丟擲自定義錯誤。

EvalError 型別的錯誤會在使用eval()函式而發生異常時被丟擲。
(注:eval() 函式可計算某個字串,並執行其中的的 JavaScript 程式碼。)
ECMA-262 中對這個錯誤有如下描述:如果以非直接呼叫的方式使用 eval 屬性的值(換句話說,沒有明確地將其名稱作為一個 Identifier,即用作 CallExpression 中的 MemberExpression),或者為 eval 屬性賦值。簡單 地說,如果沒有把 eval()當成函式呼叫,就會丟擲錯誤,例如:

new eval();
eval = foo;
//均會丟擲EvalError

RangeError 型別的錯誤會在數值超出相應範圍時觸發。例如,在定義陣列時,如果指定了陣列不支援的項數(如20或 Number.MAX_VALUE),就會觸發這種錯誤:

var items1 = new Array(-20); //丟擲RangeError 
var items2 = new Array(Number.MAX_VALUE); //丟擲RangeError

在找不到物件的情況下,會發生 ReferenceError(這種情況下,會直接導致人所共知的”object expected”瀏覽器錯誤)。通常,在訪問不存在的變數時,就會發生這種錯誤,例如:

var obj = x; //在 x 並未宣告的情況下丟擲 ReferenceError

至於 SyntaxError,當我們把語法錯誤的 JavaScript 字串傳入 eval()函式時,就會導致此類錯誤。例如:

eval("a ++ b"); //丟擲SyntaxError

TypeError 型別在 JavaScript 中會經常用到,在變數中儲存著意外的型別時,或者在訪問不存在的方法時,都會導致這種錯誤。錯誤的原因雖然多種多樣,但歸根結底還是由於在執行特定於型別的操作時,變數的型別並不符合要求所致。下面來看幾個例子:

var o = new 10; //丟擲TypeError 
alert("name" in true); //丟擲TypeError 
Function.prototype.toString.call("name"); //丟擲 TypeError

最常發生型別錯誤的情況,就是傳遞給函式的引數事先未經檢查,結果傳入型別與預期型別不相符。

在使用 encodeURI()或 decodeURI(),而 URI 格式不正確時,就會導致 URIError 錯誤。

利用不同的錯誤型別,可以獲悉更多有關異常的資訊,從而有助於對錯誤作出恰當的處理。要想知道錯誤的型別,可以像下面這樣在 try-catch 語句的 catch 語句中使用 instanceof 操作符:

try {
    someFunction();
} catch (error){
    if (error instanceof TypeError){ 
        //處理型別錯誤
    } else if (error instanceof ReferenceError){ 
        //處理引用錯誤
    } else { 
        //處理其他型別的錯誤
    }
}

使用 try-catch 最適合處理那些我們無法控制的錯誤。假設你在使用一個大型 JavaScript 庫中的函式,該函式可能會有意無意地丟擲一些錯誤。由於我們不能修改這個庫的原始碼,所以大可將對該函式的呼叫放在 try-catch 語句當中,萬一有什麼錯誤發生,也好恰當地處理它們。

丟擲錯誤

與 try-catch 語句相配的還有一個 throw 操作符,用於隨時丟擲自定義錯誤。丟擲錯誤時,必須要給 throw 操作符指定一個值,這個值是什麼型別,沒有要求。下列程式碼都是有效的:

throw 12345;
throw "Hello world!";
throw true;
throw { name: "JavaScript"};

在遇到 throw 操作符時,程式碼會立即停止執行。僅當有 try-catch 語句捕獲到被丟擲的值時,程式碼才會繼續執行。
通過使用某種內建錯誤型別,可以更真實地模擬瀏覽器錯誤。每種錯誤型別的建構函式接收一個引數,即實際的錯誤訊息。下面是一個例子:

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.");

另外,利用原型鏈還可以通過繼承 Error 來建立自定義錯誤型別,此時,需要為新建立的錯誤型別指定 name 和 message 屬性。

function CustomError(message){
    this.name = "CustomError";
    this.message = message;
}
CustomError.prototype = new Error();
throw new CustomError("My message");

瀏覽器對待繼承自 Error 的自定義錯誤型別,就像對待其他錯誤型別一樣。如果要捕獲自己丟擲的錯誤並且把它與瀏覽器錯誤區別對待的話,建立自定義錯誤是很有用的。

丟擲錯誤的時機:

要針對函式為什麼會執行失敗給出更多資訊,丟擲自定義錯誤是一種很方便的方式。應該在出現某 種特定的已知錯誤條件,導致函式無法正常執行時丟擲錯誤。換句話說,瀏覽器會在某種特定的條件下執行函式時丟擲錯誤。例如,下面的函式會在引數不是陣列的情況下失敗:

function process(values){
    values.sort();
    for (var i=0, len=values.length; i < len; i++){
        if (values[i] > 100){
            return values[i];
        }
    }
    return -1; 
}

如果執行這個函式時傳給它一個字串引數,那麼對 sort()的呼叫就會失敗。對此,不同瀏覽器會給出不同的錯誤訊息,但都不是特別明確。這種情況下,帶有適當資訊的自定義錯誤能夠顯著提升程式碼的可維護性。 來看下面的例子。

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; 
}

在重寫後的這個函式中,如果 values 引數不是陣列,就會丟擲一個錯誤。錯誤訊息中包含了函式的名稱,以及為什麼會發生錯誤的明確描述。如果一個複雜的 Web 應用程式發生了這個錯誤,那麼查詢問題的根源也就容易多了。
建議讀者在開發 JavaScript 程式碼的過程中,重點關注函式和可能導致函式執行失敗的因素。良好的錯誤處理機制應該可以確保程式碼中只發生你自己丟擲的錯誤。

錯誤事件

任何沒有通過 try-catch 處理的錯誤都會觸發 window 物件的 error 事件。
在任何 Web 瀏覽器中,onerror 事件處理程式都不會建立 event 物件,但它可以接收三個引數:錯誤訊息、錯誤所在的 URL 和行號。

window.onerror = function(message, url, line){
    alert(message);
};

只要發生錯誤,無論是不是瀏覽器生成的,都會觸發 error 事件,並執行這個事件處理程式。然後,瀏覽器預設的機制發揮作用,像往常一樣顯示出錯誤訊息。像下面這樣在事件處理程式中返回 false,可以阻止瀏覽器報告錯誤的預設行為:

window.onerror = function(message, url, line){
    alert(message);
    return false;
};

通過返回 false,這個函式實際上就充當了整個文件中的 try-catch 語句,可以捕獲所有無程式碼處理的執行時錯誤。這個事件處理程式是避免瀏覽器報告錯誤的最後一道防線,理想情況下,只要可能就不應該使用它。只要能夠適當地使用 try-catch 語句,就不會有錯誤交給瀏覽器,也就不會觸發 error 事件。

影象也支援 error 事件。只要影象的 src 特性中的 URL 不能返回可以被識別的影象格式,就會觸發 error 事件。此時的 error 事件遵循 DOM 格式,會返回一個以影象為目標的 event 物件。下面是 一個例子。

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"; //指定不存在的檔案

在這個例子中,當載入影象失敗時就會顯示一個警告框。需要注意的是,發生 error 事件時,影象下載過程已經結束,也就是說不能再重新下載了。

處理錯誤的策略

在 Web 應用程式的 JavaScript 這一端,錯誤處理策略同伺服器端一樣重要。由於任何 JavaScript 錯誤都可能導致網頁無法使用,因此搞清楚何時以及為什麼發生錯誤至關重要。
絕大多數 Web 應用程式的使用者都不懂技術,遇到錯誤時很容易心煩意亂。有時候,他們可能會重新整理頁面以期解決問題,而有時候則會放棄努力。作為開發人員,必須要知道程式碼何時可能出錯,會出什麼錯,同時還要有一個跟蹤此類問題的系統。

常見的錯誤型別

一般來說,需要關注三種錯誤:
型別轉換錯誤
資料型別錯誤
通訊錯誤

型別轉換錯誤:

型別轉換錯誤發生在使用某個操作符,或者使用其他可能會自動轉換值的資料型別的語言結構時。
在使用相等(==)和不相等(!=)操作符,或者在 if、for 及 while 等流控制語句中使用非布林值時, 最常發生型別轉換錯誤。

相等和不相等操作符在執行比較之前會先轉換不同型別的值。由於在非動態語言中, 開發人員都使用相同的符號執行直觀的比較,因此在 JavaScript 中往往也會以相同方式錯誤地使用它們。 多數情況下,我們建議使用全等(===)和不全等(!==)操作符,以避免型別轉換。

alert(5 == "5");//true
alert(5 === "5");//false
alert(1 == true);//true
alert(1 === true);//false

這裡使用了相等和全等操作符比較了數值5和字串”5”。相等操作符首先會將數值5轉換成字元 串”5”,然後再將其與另一個字串”5”進行比較,結果是 true。全等操作符知道要比較的是兩種不同的資料型別,因而直接返回 false。對於 1 和 true 也是如此:相等操作符認為它們相等,而全等操作 符認為它們不相等。使用全等和非全等操作符,可以避免發生因為使用相等和不相等操作符引發的型別轉換錯誤,因此我們強烈推薦使用。

容易發生型別轉換錯誤的另一個地方,就是流控制語句。像 if 之類的語句在確定下一步操作之前,會自動把任何值轉換成布林值。尤其是 if 語句,如果使用不當,最容易出錯。來看下面的例子:

function concat(str1, str2, str3){
    var result = str1 + str2;
    if (str3){ //絕對不要這樣!!!
          result += str3;
    }
    return result;
}

// 修改
function concat(str1, str2, str3){ 
    var result = str1 + str2;
    if (typeof str3 == "string"){//恰當的比較
        result += str3;
    }
    return result;
}

在這個重寫後的函式中,if 語句的條件會基於比較返回一個布林值。這個函式相對可靠得多,不 容易受非正常值的影響。

資料型別錯誤:

JavaScript 是鬆散型別的,也就是說,在使用變數和函式引數之前,不會對它們進行比較以確保它們的資料型別正確。為了保證不會發生資料型別錯誤,只能依靠開發人員編寫適當的資料型別檢測程式碼。 在將預料之外的值傳遞給函式的情況下,最容易發生資料型別錯誤。

//不安全的函式,任何非字串值都會導致錯誤:indexOf和substring函式只能操作字串,因此只要傳入其他資料型別的值就會導致錯誤。
function getQueryString(url){
    var pos = url.indexOf("?");
    if (pos > -1){
        return url.substring(pos +1);
    }
    return ""; 
}

function getQueryString(url){
    if (typeof url == "string"){ //通過檢查型別確保安全 
        var pos = url.indexOf("?");
        if (pos > -1){
                return url.substring(pos +1);
        }
    }
    return ""; 
}

前面提到過,在流控制語句中使用非布林值作為條件很容易導致型別轉換錯誤。
同樣,這樣做也經常會導致資料型別錯誤。來看下面的例子。

//不安全的函式,任何非陣列值都會導致錯誤 
function reverseSort(values){
    if (values){ //絕對不要這樣!!! 
        values.sort();
        values.reverse();
     }
}
//安全,非陣列值將被忽略 
function reverseSort(values){
    if (values instanceof Array){
        values.sort();
        values.reverse();
    } 
}

大體上來說,基本型別的值應該使用 typeof 來檢測,而物件的值則應該使用 instanceof 來檢測。

根據使用函式的方式,有時候並不需要逐個檢測所有引數的資料型別。但是,面向公眾的 API 則必須無條件地執行型別檢查,以確保函式始終能夠正常地執行。

通訊錯誤:

隨著 Ajax 程式設計的興起,Web 應用程式在其生命週期內動態載入資訊或功能, 已經成為一件司空見慣的事。不過,JavaScript 與伺服器之間的任何一次通訊,都有可能會產生錯誤。

對於查詢字串,應該記住必須要使用 encodeURIComponent()方法。為了確保這一點,有時候可以定義一個處理查詢字串的函式,例如:

function addQueryStringArg(url, name, value){
    if (url.indexOf("?") == -1){
        url += "?";
    } else {
        url += "&"; 
    }
    url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
    return url; 
}

var url = "http://www.somedomain.com";
var newUrl = addQueryStringArg(url, "redir", "http://www.someotherdomain.com?a=b&c=d");
alert(newUrl);

另外,在伺服器響應的資料不正確時,也會發生通訊錯誤。在沒有返回相應資源的情況下,Firefox、 Chrome 和 Safari 會默默地失敗,IE 和 Opera 則都會報錯。在某些情況下,使用 Ajax 通訊可以提供有關錯誤狀態的更多資訊。

區分致命錯誤和非致命錯誤

把錯誤記錄到伺服器

開發 Web 應用程式過程中的一種常見的做法,就是集中儲存錯誤日誌,以便查詢重要錯誤的原因。

例如資料庫和伺服器錯誤都會定期寫入日誌,而且會按照常用 API 進行分類。在複雜的 Web 應用程式中,我們同樣推薦你把 JavaScript 錯誤也回寫到伺服器。換句話說,也要將這些錯誤寫入到儲存伺服器端錯誤的地方,只不過要標明它們來自前端。把前後端的錯誤集中起來,能夠極大地方便對資料的分析。

要建立這樣一種 JavaScript 錯誤記錄系統,首先需要在伺服器上建立一個頁面(或者一個伺服器入口點),用於處理錯誤資料。這個頁面的作用無非就是從查詢字串中取得資料,然後再將資料寫入錯誤日誌中。

這個頁面可能會使用如下所示的函式:

function logError(sev, msg){
    var img = new Image();
    img.src = "log.php?sev=" + encodeURIComponent(sev) + "&msg=" + encodeURIComponent(msg);
}

這個 logError()函式接收兩個引數:表示嚴重程度的數值或字串(視所用系統而異)及錯誤訊息。其中,使用了 Image 物件來發送請求,這樣做非常靈活,主要表現如下幾方面。
所有瀏覽器都支援 Image 物件,包括那些不支援 XMLHttpRequest 物件的瀏覽器。
可以避免跨域限制。通常都是一臺伺服器要負責處理多臺伺服器的錯誤,而這種情況下使用XMLHttpRequest 是不行的。
在記錄錯誤的過程中出問題的概率比較低。大多數 Ajax 通訊都是由 JavaScript 庫提供的包裝函式來處理的,如果庫程式碼本身有問題,而你還在依賴該庫記錄錯誤,可想而知,錯誤訊息是不可能得到記錄的。

只要是使用 try-catch 語句,就應該把相應錯誤記錄到日誌中。來看下面的例子。

for (var i=0, len=mods.length; i < len; i++){
    try {
        mods[i].init();
    } catch (ex){
        logError("nonfatal", "Module init failed: " + ex.message);
    } 
}

在這裡,一旦模組初始化失敗,就會呼叫 logError()。第一個引數是”nonfatal”(非致命),表 示錯誤的嚴重程度。第二個引數是上下文資訊加上真正的 JavaScript 錯誤訊息。記錄到伺服器中的錯誤訊息應該儘可能多地帶有上下文資訊,以便鑑別導致錯誤的真正原因。

3、除錯技術

將訊息記錄到控制檯

IE8、Firefox、Opera、Chrome 和 Safari 都有 JavaScript 控制檯,可以用來檢視 JavaScript 錯誤。而且,在這些瀏覽器中,都可以通過程式碼向控制檯輸出訊息。

可以通過 console 物件向 JavaScript 控制檯中寫入訊息,這個物件具有下列方法:
error(message):將錯誤訊息記錄到控制檯
info(message):將資訊性訊息記錄到控制檯
log(message):將一般訊息記錄到控制檯
warn(message):將警告訊息記錄到控制檯

Opera 10.5 之前的版本中,JavaScript 控制檯可以通過 opera.postError()方法來訪問。這個方法接受一個引數,即要寫入到控制檯中的引數,其用法如下:

opera.postError("message");

還有一種方案是使用 LiveConnect,也就是在 JavaScript 中執行 Java 程式碼。Firefox、Safari 和 Opera 12 都支援 LiveConnect,因此可以操作 Java 控制檯。例如,通過下列程式碼就可以在 JavaScript 中把訊息寫入到 Java 控制檯:

java.lang.System.out.println("Your message");

不存在一種跨瀏覽器向 JavaScript 控制檯寫入訊息的機制,但下面的函式倒可以作為統一的介面。

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);
    }
}

將訊息記錄到當前頁面

另一種輸出除錯訊息的方式,就是在頁面中開闢一小塊區域,用以顯示訊息。這個區域通常是一個 元素,而該元素可以總是出現在頁面中,但僅用於除錯目的;也可以是一個根據需要動態建立的元素。

這種方式下,頁面中會有一小塊區域顯示錯誤訊息。這種技術在不支援 JavaScript 控制檯的 IE7 及更早版本或其他瀏覽器中十分有用。

丟擲錯誤

如前所述,丟擲錯誤也是一種除錯程式碼的好辦法。如果錯誤訊息很具體,基本上就可以把它當作確 定錯誤來源的依據。
對於大型應用程式來說,自定義的錯誤通常都使用 assert()函式丟擲。這個函式接受兩個引數, 一個是求值結果應該為 true 的條件,另一個是條件為 false 時要丟擲的錯誤。以下就是一個非常基本 的 assert()函式:

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

可以用這個 assert()函式代替某些函式中需要除錯的 if 語句,以便輸出錯誤訊息。下面是使用這個函式的例子:

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

可見,使用 assert()函式可以減少丟擲錯誤所需的程式碼量,而且也比前面的程式碼更容易看懂。

4、常見的IE錯誤

操作終止
無效字元
未找到成員
未知執行時錯誤
語法錯誤
系統無法找到指定資源

相關推薦

JavaScript筆記錯誤處理除錯

1、瀏覽器報告的錯誤 IE IE 是唯一一個在瀏覽器的介面窗體(chrome)中顯示 JavaScript 錯誤資訊的瀏覽器。在發生 JavaScript 錯誤時,瀏覽器左下角會出現一個黃色的圖示,圖示旁邊則顯示著”Error on page”(頁面中有錯誤

Javascript 高階程式設計(第三版)》筆記0x1E 錯誤處理除錯

目錄 瀏覽器報告的錯誤 錯誤處理     try-catch語句         finally 子句         錯誤型別      

17.錯誤處理除錯——JavaScript高階程式設計(筆記)

00.請讀者務必要記住,只要程式碼中包含finally子句,那麼無論try還是catch語句塊中的return語句都將被忽略。因此,在使用finally子句之前,一定要非常清楚你想讓程式碼怎樣。 01.錯誤型別(Error EvalError RangeError ReferenceError Synatx

javascript錯誤處理除錯

    本文主要介紹javascript中一些常見的錯誤,以及一些用於除錯和處理錯誤的基礎,以幫助我們提高javascript程式碼的質量. 先說下javascript中常見的7種錯誤: 1.變數未定義 下面的語句將隱式的建立一個新的變數abc,並將值123賦給該變數

JavaScript】(4)——錯誤處理除錯

背景:JavaScript在錯誤處理除錯上一直是它的軟肋,如果指令碼出錯,給出的提示經常也讓人摸不著頭腦。ECMAScript第3版為了解決這個問題引入了 try...catch和 throw語句以及一些錯誤型別,讓開發人員更加適時的處理錯誤。良好的錯誤處理機制可以及時的提

關於JavaScript的學習(十七)——錯誤處理除錯

第十七章   錯誤處理對於今天覆雜的Web應用程式開發而言至關重要。不能提前預測到可能發生的錯誤,不能提前採取回覆策略,可能導致較差的使用者體驗,最終引發使用者不滿。多數瀏覽器在預設情況下都不會向用戶報告錯誤,因此在開發和除錯期間需要啟動瀏覽器的錯誤報告功

JavaScriptFireFox的不解之緣——錯誤處理除錯

       作為IT界的一員出現Bug真是在正常不過。在學習JavaScript的時候難免自己因為各種原因而導致出錯,知道錯誤是什麼之後才能快準狠的修改之。在學習過程中都習慣使用火狐瀏覽器進行檢視效

javascript錯誤處理除錯(轉)

JavaScript 在錯誤處理除錯上一直是它的軟肋,如果指令碼出錯,給出的提示經常也讓人摸不著頭腦。 ECMAScript 第 3 版為了解決這個問題引入了 try...catch 和 throw 語句以及一些錯誤型別,讓開發人員更加適時的處理錯誤。 一.瀏覽器錯誤報告

JS錯誤處理除錯

try{ window.someNonexistentFunction(); }catch(error){ console.log(error.message); } 錯誤物件的message屬性。 自己在做了一個例子。 try{ (function(){

JavaScript(六)錯誤處理機制

image || .cn final nta 構造函數 n) 示例 發生 1.Error()構造函數 javascript解析或執行語句時,一旦發生錯誤,js引擎會將其拋出! JavaScript原生提供了Error()構造函數,所有拋出的錯誤都是這個構造函數的實例(即對象

浙大《面向物件程式設計--java語言》學習筆記(第八週異常處理輸入輸出)

8.1 異常 ArrayIndex.java package exception; import java.util.Scanner; public class ArrayIndex { public static void main(String[] args) { // TO

筆記mysql 下載安裝

blog utf8 字符 data strong def services -1 個人 1.下載: 官網下載是需要註冊的,或者你已經有了Oracle的賬號. 可以直接百度 mysql 進入官網;或者直接下面的鏈接; 附上鏈接:dev.mysql.com/downloa

[Other]面試復習筆記線程進程復習

處理機 sse 進程上下文 提高 關系 數據查詢 優點 con 計數器 基本概念1. 進程的基本概念線程(thread)是進程(processes)中某個單一順序的控制流,也被稱為輕量進程(lightweight processes)。進程是表示資源分配的基本單位,又是調

C#學習筆記處理指令

copy erro log com 學習 tco endif href 指定 C#和C/C++一樣,也支持預處理指令,下面我們來看看C#中的預處理指令。 #region 代碼折疊功能,配合#endregion使用,如下: 點擊後如下: 條件預處理 條件預處

張高興的 Xamarin.Forms 開發筆記為 Android iOS 引入 UWP 風格的漢堡菜單 ( MasterDetailPage )

操作 using eat stp 取消 height 新建 屬性 turn   所謂 UWP 樣式的漢堡菜單,我曾在“張高興的 UWP 開發筆記:漢堡菜單進階”裏說過,也就是使用 Segoe MDL2 Assets 字體作為左側 Icon,並且左側使用填充顏色的矩形用來表示

Java筆記異常處理

parseint runtime pan exceptio 定義 bound 頂部 args tostring 一、基礎知識 異常是用來描述代碼中發生的異常情況的對象。當出現引起異常的情況時,就會拋出異常對象。方法可以選擇自己處理異常或繼續拋出異常。異常可以由Java運行時

ASP.NET MVC編程——錯誤處理日記

CP 引用 args context mvc4 strong gpo pub family ASP.NET MVC的錯誤處理應考慮到這幾個方面:模型綁定期間發生的錯誤,未能路由到指定操作,針對控制器的錯誤處理。使用配置文件可以幫助我們處理異常,但是不夠靈活和全面;使用Han

SpringMVC學習筆記單例並發問題

一個 獲得 app parseint 本地服務 屬性 als min c學習 Spring中的Bean默認都是單例(singleton),Spring中Bean的scope屬性有五種類型: singleton 表示在spring容器中的單例,通過spring容器獲得該be

大數據爭論處理處理的C位之戰

數據管理 sha 區別 mark spark 連續 錘子 常用 兩種 數據無疑是當今數字經濟中的新貨幣,但要跟上企業數據變化和遞增的業務信息需求,仍然是非常艱難。這也就解釋了公司將數據從傳統基礎構架中遷移至雲中,以衡量數據驅動決策的原因。這可確保公司寶貴資源——數據——受到

筆記MyBatis中$#的區別

首先MyBatis中 $與#都是動態傳參 # 將傳入的資料都當成一個字串,會對自動傳入的資料加一個雙引號 $ 將傳入的資料直接顯示生成在sql中 # 佔位符號,能夠很大程度防止sql注入「語句的拼接」 $ sql拼接符號,無法防止Sql注入 如果使用在order by中就需要使用 $