javascript|異常處理 問題:
希望在使用者視圖之外處理指令碼錯誤(異常),避免瀏覽器向使用者報告錯誤資訊。
解決方案:
一種quick-and-dirty(快餐式?),向後相容的方式是:將下面的代碼置於頁面的<head></head>節內:
function doNothing(){ return true; }
window.onerror = doNothing; 這樣不會阻止編譯期的指令碼錯誤(例如頁面載入時解譯器發現的語法錯誤),也不會向你透露代碼的何處潛伏著錯誤。所以只有你的代碼經過了充分的測試後才使用這種方法,在測試的時候,要把這些代碼去掉。
在IE5和Netscape6及它們的後續版本中,你可以使用更多的錯誤(異常)處理方式。為防止早期的瀏覽器執行這些特殊的指令碼時失敗,將這些語句所在的<script>標籤的language屬性設定為JavaScript1.5(language="JavaScript1.5")。
將可能導致或拋出異常的語句封裝在一個try...catch...finally結構中。先執行try塊中的語句,其中包含可能發生異常的代碼,如果發生異常,則執行catch塊中的代碼,而不管是否發生異常,最後會無條件執行finally塊的語句:
<script language="javascript1.5">
try
{
//tryStatements
}
catch(ex)
{
//catchStatements;
}
finally
{
//finallyStatements;
}
</script>
每個被拋出的異常都會產生一個Error對象的執行個體,該對象的引用可以作為catch子句的參數,如上面代碼的ex參數,catch子句中的語句可以查看該對象的屬性以獲得更多資訊。到目前為止,在ECMAScript標準中只有兩個屬性得到正式認可,即message和name。一些瀏覽器則實現了更多的屬性:
屬性
|
IE的支援 |
NN的支援 |
描述 |
description
|
5
|
n/a
|
異常的描述資訊
|
fileName |
n/a
|
6 |
拋出異常的指令碼所在檔案的URI |
lineNumber
|
n/a
|
6
|
拋出異常的代碼的行號
|
message
|
5.5
|
6
|
異常的描述資訊(ECMA)
|
name
|
5.5
|
6
|
異常類型(ECMA)
|
number
|
5
|
n/a
|
IE專屬的異常代號
|
比如,我們可以寫這樣一段代碼:
try
{
colors[2] = "red";
}
catch(e)
{
alert("An exception occured in the script.Error name: " + e.name
+ ".Error message: " + e.message);
} 要訪問colors索引為2的元素,會引發一個異常:colors is not defined。catch塊中的語句會告訴使用者一些簡單的資訊。這看起來不錯,可以用這種方法給使用者顯示一些比較友好的資訊。
等等,還要注意,這裡的catch語句會捕捉所有類型的異常。想想在C#中,我們需要盡量避免捕獲通用的Exception類型的異常,因為它太通用了,我們有時還希望能針對不同類型的異常採取不同的應對方法。這裡也是一樣,幸運的是,JavaScript中也有一些特定類型的異常。比如,對於上面代碼引發的異常,我們可以這麼寫:
try
{
colors[2] = "red";
}
catch(e)
{
if(e instanceof TypeError)
{
alert("An exception occured in the script.Error name: " + e.name
+ ".Error message: " + e.message);
}
} 在捕獲異常後,會進行異常類型的判斷,只處理TypeError類型的異常,其他類型的則忽略。
JavaScript中共有六種基本的異常類型:
- EvalError : 在錯誤的調用eval()函數時引發;
- RangeError : 在一個數字型變數的值超出了其範圍時引發;
- ReferenceError : 在使用一個無效的引用時引發;
- SyntaxError : 在解析JavaScript代碼時其中的語法錯誤引發;
- TypeError : 遇到一個意外的類型時引發;
- URIError : 錯誤地使用encodeURI()或decodeURI()函數時引發。
下面的代碼示範了嵌套的異常處理的流程:
try
{
print("Outer try running..");
try
{
print("Nested try running...");
throw "an error";
}
catch(e)
{
print("Nested catch caught " + e);
throw e + " re-thrown";
}
finally
{
print("Nested finally is running...");
}
}
catch(ex)
{
print("Outer catch caught " + ex);
}
finally
{
print("Outer finally running");
}
function print(s)
{
document.write(s);
} 這裡使用throw語句拋出一個異常,throw語句可以拋出任意對象。
輸出結果為:
Outer try running..
Nested try running...
Nested catch caught an error
Nested finally is running...
Outer catch caught an error re-thrown
Outer finally running
異常的資訊不要讓使用者看到。使用message屬性來決定如何處理異常。
也可以在指令碼中有意識地拋出異常建立自己的異常處理機制。看下面的樣本:
function processNumber(inputField)
{
try
{
var inpVal = parseInt(inputField.value, 10);
if(isNaN(inpVal))
{
var msg = "Please enter a number!";
var err = new Error(msg);
if(!err.message)
{
err.message = msg;
}
throw err;
}
}
catch(e)
{
alert(e.message);
inputField.focus();
inputField.select();
}
} 在try塊中檢測表單域的值,如果不合要求,則拋出自訂異常,catch塊會捕獲該異常,在這裡進行相應的處理。