javascript|錯誤|技巧|網頁
不管你的技術水平如何,錯誤或異常是應用程式開發人員生活的一部分。Web開發的不連貫性留下了許多錯誤能夠發生並確實已經發生的地方。解決的關鍵在於處理任何不可預見的(或可預見的錯誤),來控制使用者的體驗。利用JavaScript,就有多種技術和語言特色可以用來正確地解決任何問題。
事事檢查
在開始之前檢查一切是一個好的編程習慣,也就是說,你應該在利用它們之前,檢查對象、方法調用等的有效性。這樣就避免了與未執行個體化對象或對不存在的方法調用有關的錯誤。列表A在使用對象(變數和欄位)之前會對它們進行檢查。在使用欄位對象之前,該指令碼保證它們為有效或非空欄位。
列表A
<html>
<head>
<title>JS Test</title>
<script type="text/javascript">
function validate() {
var doc = document.forms[0];
var flag = true;
if (doc != null) {
if (doc.fullName != null) {
if (doc.fullName.value == '') {
flag = false;
}
} else {
flag = false;
}
if (doc.contactNumber != null) {
if (doc.contactNumber.value == '') {
flag = false;
}
} else {
flag = false;
}
if (flag) {
alert('Validation successful, document will be submitted.');
doc.submit();
} else {
alert('Enter values before submitting.');
} }
return 0; }
</script>
</head>
<body>
<form id="frmTest">
Name: <input id="fullName" name="fullName" type="text"><br>
Address: <input id="contactNumber" name="contactNumber" type="text"><br>
<input type="button" value="Submit" >
</form>
</body>
</html>
你並不需要實際地檢查有效性——你可以簡單地在if 語句中使用一個對象,如果它不是一個無效對象的話,所求得的值就為真。列表B就用了這種句法,同時也用到了getElementByID方法。它用了一個if語句來保證在繼續之前getElementByID方法是被支援的(存在)。
列表B
<html><head>
<title>JS Test</title>
<script type="text/javascript">
function validate() {
var doc = document.forms[0];
var flag = true;
if (doc != null) {
if (doc.getElementById) {
if (doc.getElementById("fullName")) {
if (doc.fullName.value == '') {
flag = false;
}
} else {
flag = false;
}
if (doc.getElementById("contactNumber")) {
if (doc.contactNumber.value == '') {
flag = false;
}
} else {
flag = false;
}
if (flag) {
alert('Validation successful, document will be submitted.');
doc.submit()
} else {
alert('Enter values before submitting.');
} }
return 0; }
</script>
</head>
<body>
<form id="frmTest">
Name: <input id="fullName" name="fullName" type="text"><br>
Address: <input id="contactNumber" name="contactNumber" type="text"><br>
<input type="button" value="Submit" >
</form>
</body>
</html>
雖然在使用對象之前檢查它們是一個好方法,但是有時候還是會有錯誤出現。在這些執行個體中,JavaScript語言使得發現錯誤變得簡單,從而能夠繼續下去。
發現錯誤
和Java、C#等其他語言相類似,JavaScript中包括了try/catch/finally語句。一個try語句包含了一組代碼,在這組代碼中,像已耗用時間錯誤這樣的異常可能會發生。catch子句概述了怎樣處理錯誤,finally塊中包括了始終被執行的代碼。
一般來說,代碼設法執行一組代碼,如果沒有執行成功的話,支配權就傳到catch塊。如果沒有錯誤發生,就跳過catch塊。finally塊在try和catch塊完畢後執行。它的句法如下:
try
{
// code
}
catch
{
// code
}
finally
{
// code
}
catch和finally塊是可選的,但是如果沒有catch塊是沒有意義的。仔細考慮列表C,它示範了try/catch/finally的用法。從被引用的欄位在表格中不存在開始,錯誤就發生了。
列表C
<html>
<head>
<title>JS Test</title>
<script type="text/javascript">
function doIt() {
if (document.forms[0].firstName.value == '') {
// do something
}
return 0; }
</script>
</head>
<body>
<form id="frmTest">
Name: <input id="fullName" name="fullName" type="text"><br>
Address: <input id="contactNumber" name="contactNumber" type="text"><br>
<input type="button" value="Submit" >
</form>
</body>
</html>
一個try/catch塊不能避免錯誤,但是它能夠很得體地處理錯誤,這樣使用者就不會面對晦澀的瀏覽器出錯資訊。觀察列表D。
列表D
<html>
<head>
<title>JS Test</title>
<script type="text/javascript">
function doIt() {
try {
if (document.forms[0].firstName.value == '') {
// do something
}
} catch(e) {
document.write("An unexpected error has occurred.<br><br>");
document.write("Please contact the administrator.<br><br>");
document.write(e.message);
} finally {
document.forms[0].submit();
}
return 0; }
</script></head>
<body>
<form id="frmTest">
Name: <input id="fullName" name="fullName" type="text"><br>
Address: <input id="contactNumber" name="contactNumber" type="text"><br>
<input type="button" value="Submit" >
</form></body></html>
它提示了以下資訊,但是finally塊保證了表單的提交——不管有什麼錯誤發生。
An unexpected error has occurred.
Please contact the administrator.
'document.forms.0.firstName.value' is null or not an object
單個catch塊可以處理所有問題,但是多個catch語句可以被用來處理特定的錯誤。這個問題在下個部分會涉及到。
用try/catch語句可以很容易地處理不可預見的錯誤。在某些情況下,可能你想以不同的方式處理錯誤,JavaScript提供了throw語句。它的句法是很基本的——throw後面緊跟要發生的異常。這就使得你能夠定義和引發自訂的異常。列表E中的代碼建立了一個缺失值的異常,並且它是產生的。
列表E
<html><head>
<title>JS Test</title>
<script type="text/javascript">
function MissingValueException (errMsg) {
this.message = errMsg;
this.name="MissingValueException";
}
function doIt() {
try {
if (document.forms[0].fullName.value == '') {
noNameException = new MissingValueException("First name is missing.");
throw noNameException;
} else {
document.forms[0].submit();
}
} catch(e) {
document.write("An unexpected error has occurred.<br>");
document.write("Please contact the administrator.<br>");
document.write(e.message);
} finally {
document.forms[0].submit();
}
return 0; }
</script></head><body>
<form id="frmTest">
Name: <input id="fullName" name="fullName" type="text"><br>
Address: <input id="contactNumber" name="contactNumber" type="text"><br>
<input type="button" value="Submit" >
</form></body></html>
它將會顯示以下資訊(如果在欄位中沒有值輸入的話):
An unexpected error has occurred.
Please contact the administrator.
First name is missing.
除此之外,你還可以用運算子instanceof來確定異常的類型,從而做出反應。列表F中的代碼會檢查異常對象的類型並相應地顯示有關資料。
列表F
<html>
<head>
<title>JS Test</title>
<script type="text/javascript">
function MissingValueException (errMsg) {
this.message = errMsg;
this.name="MissingValueException";
}
function doIt() {
try {
if (document.forms[0].fullName.value == '') {
noNameException = new MissingValueException("First name is missing.");
throw noNameException;
}
} catch(e) {
if (e instanceofMissingValueException) {
document.write(e.message + "<br>");
document.write("Please contact the administrator.<br><br>");
} else {
document.write("An unexpected error has occurred.<br>");
document.write("Please contact the administrator.<br>");
document.write(e.message);
} } finally {
document.forms[0].submit();
} return 0; }
</script></head><body>
<form id="frmTest">
Name: <input id="fullName" name="fullName" type="text"><br>
Address: <input id="contactNumber" name="contactNumber" type="text"><br>
<input type="button" value="Submit" >
</form></body></html>
運算子instanceof可以同標準錯誤一起使用。JavaScript定義了以下標準的JavaScript錯誤類型:
EvalError:表明全域的eval函數使用錯誤。
RangeError:說明一個數值超過了所允許的值的範圍。
ReferenceError:發現了一個非法的引用。
SyntaxError:發生了一個句法分析錯誤。
TypeError:一個運算元的實際類型與所預期的類型不同。
URIError:其中一個全域URI函數(編碼URI或解碼URI)使用錯誤。
列表G中的代碼在一個catch語句中採用了TypeError類型。由於在引用欄位名(document)的行中多了一個d,結果發生了一個打字錯誤(ddocument)。
列表G
<html><head>
<title>JS Test</title>
<script type="text/javascript">
function MissingValueException (errMsg) {
this.message = errMsg;
this.name="MissingValueException";
}
function doIt() {
try {
if (ddocument.forms[0].fullName.value == '') {
noNameException = new MissingValueException("First name is missing.");
throw noNameException;
}
} catch(e) {
if (e instanceofTypeError) {
document.write("Reference error while accessing First Name field.<br><br>");
document.write("Please contact the administrator.<br><br>");
document.write(e.message);
} else {
document.write("An unexpected error has occurred.<br><br>");
document.write("Please contact the administrator.<br><br>");
document.write(e.message);
} } finally {
document.forms[0].submit();
} return 0; }
</script></head>
<body><form id="frmTest">
Name: <input id="fullName" name="fullName" type="text"><br>
Address: <input id="contactNumber" name="contactNumber" type="text"><br>
<input type="button" value="Submit" >
</form></body></html>
處理所有的分頁錯誤
另一個你可以自行支配的特性是window.onerror事件。和所有其他的JavaScript事件一樣,你可以定義一個函數或者一條代碼在事件被觸發時運行。它可以用來處理或忽略錯誤。列表H中的頁面顯示了遇到的所有JavaScript錯誤的簡單資訊。因為指定的函數不存在,所以當點擊按鈕時,錯誤就發生了。列表I是用onerror事件來忽略所有的錯誤的。
列表H
<html><head>
<title>onError Test</title>
<script type="text/javascript">
function handleErrors() {
alert("A JavaScript error has occurred.");
return true;
}
window.onerror = handleErrors;
</script></head>
<body>
<form id="frmTest">
Name: <input id="fullName" name="fullName" type="text"><br>
Address: <input id="contactNumber" name="contactNumber" type="text"><br>
<input type="button" value="Submit" >
</form></body></html>
列表I
<html><head>
<title>JS Test</title>
<script type="text/javascript">
function ignoreErrors() {
return true;
}
window.onerror = ignoreErrors;
</script></head>
<body><form id="frmTest">
Name: <input id="fullName" name="fullName" type="text"><br>
Address: <input id="contactNumber" name="contactNumber" type="text"><br>
<input type="button" value="Submit" >
</form></body></html>
關於onerror事件的一個問題是瀏覽器的支援。最大的問題就發生在Opera瀏覽器中,所以在把瀏覽器和自己的應用程式相結合之前,你應該確保所有的目標瀏覽器都支援這一特性。
謹慎處理
錯誤是每一個應用程式的一部分,但是適當的錯誤處理卻不是。合理地運用JavaScript的錯誤處理特色和自動靈活的解碼可以使使用者的體驗更順暢,同時也讓開發方的診斷工作變得更輕鬆。