不管你的技術水平如何,錯誤或異常是應用程式開發者生活的一部分。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" onclick="validate();"> </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" onclick="validate();"> </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" onclick="doIt();"> </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" onclick="doIt();"> </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" onclick="doIt();"> </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" onclick="doIt();"> </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" onclick="doIt();"> </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" onclick="doIt();"> </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" onclick="doIt();"> </form></body></html> |
謹慎處理
錯誤是每一個應用程式的一部分,但是適當的錯誤處理卻不是。合理地運用JavaScript的錯誤處理特色和自動靈活的解碼可以使用戶的體驗更順暢,同時也讓開發方的診斷工作變得更輕鬆。