一、错误处理
错误处理在程序设计中的重要性是毋庸置疑的,任何有影响力的web应用程序都需要一套完善的错误处理机制。良好的错误机制可以让用户得到提醒,知道发生了什么事。
1、try-catch语句
try-catch语句是javascript处理异常的一种标准方式,它的结构如下:
try{ // 把所有可能出现错误的代码放在try语句中 }catch(err){ // 把用于处理错误的块放在catch语句中 // catch块会接受到一个保存错误信息的对象 // 该对象的message属性是唯一一个能够保证所有浏览器都支持的属性 alert(err.message); }finally{ // finally子句无论如何都会执行 }
2、错误类型
javascript有7种错误类型,其中,Error是基类型,其他错误都继承自该类型。
- Error
- EvalError
- RangeError
- ReferenceError
- SyntaxError
- TypeError
- URIError
// eval()会计算字符串中的值,并执行其中的js代码 // 正确使用 eval("2+3"); // ECMA-262规定,如果没有把eval()当做函数调用,就会发生错误;但实践中,浏览器不一定会在应该抛出错误的时候就抛出EvalError new eval(); eval = fool
// RangeError类型的错误会在数值超过相应范围时触发 var item1 = new Array(-20); var item2 = new Array(Number.MAX_VALUE);
// 在找不到对象的情况下,会发生ReferenceError var obj=x;
// 把语法错误的字符串给eval()时,会导致SyntaxError eval("1++2");
// 在变量中保存意外的类型,或访问不存在的方法时,都会抛出TypeError错误 var o = new 10; alert("name" in true);
3、抛出错误
使用throw语句,可以抛出上述的错误,也可以抛出自定义的错误;在遇到throw操作符时,代码会立刻停止执行。
// 抛出常规错误 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't doesn't evaluate."); throw new URIError("Uri, is that you?"); throw new ReferenceError("You didn't cite your references properly."); // 抛出自定义错误 function CustomError(message){ this.name = "CustomError"; this.message = message; } CustomError.prototype = new Error(); throw new CustomError("My message");
4、常见的错误类型
一般来说,需要关注三种类型的错误:
- 类型转换错误
- 数据类型错误
- 通信错误
a)类型转换错误
为避免类型转换错误,建议使用全等操作符:
alert(5=="5");//true alert(5==="5");//false
流控制语句也很容易出错。像if之类的语句,在确定下一步操作之前,会自动把任何值转化成布尔值:
function concat(str1, str2, str3){ var result = str1 + str2; if(str3){ //当str3是大于0的数字,不是string类型时,也会执行 resutl += str3; } return result; } // 正确的写法 function concat(str1, str2, str3){ var result = str1 + str2; if(typeof str3=="string"){ resutl += str3; } return result; }
b)数据类型错误
在将变量传递个函数时,对变量进行类型进行检测,可以避免类型错误:
// 不安全的函数,任何非字符串都会导致错误 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 ""; } }
在确切知道应该传入什么类型的情况下,应该使用instanceof Array来检测类型:
/ 不安全的函数,任何非数组类型都会导致错误 function reverseSort(values){ if(values){ values.sort(); valuse.reverse(); } } // 不安全的函数,任何非数组类型都会导致错误 function reverseSort(values){ if(values != null){ values.sort(); valuse.reverse(); } } // 不安全的函数,不能只针对某个特性进行检测 function reverseSort(values){ if(typeof values.sort == "function"){ values.sort(); valuse.reverse(); } } // 安全,非数组将被忽略 function reverseSort(values){ if(values instanceof Array){ values.sort(); valuse.reverse(); } }
c)数据通信错误
常见的数据通信错误是把数据发给服务器之前,没有使用encodeURIComponent()对数据进行编码,可以定义一个处理查询字符串的函数:
function addQueryStringArg(url, name ,value){ if(url.indexOf("?") == -1){ url += "?"; }else{ url += "&"; } url += encodeURIComponent(name) + "=" +encodeURIComponent(value); return url; } var url = "http://www.baidu.com"; var newUrl = addQueryStringArg(url, "redir", "http://wwww.someotherdomain.com?a=b&b=c"); alert(newUrl);
5、非致命错误与致命错误:
非致命错误:不影响用户的主要任务/只影响页面的一部分/可以恢复/重复相同操作可以消除错误
这类错误没有必要对用户给出提示---可以直接把页面中受影响的区域替换掉。
致命错误:应用程序根本无法运行/错误明显影响到了用户的主要操作/会导致其他连带错误
这类错误应该立即给用户发送消息,告诉他们无法继续进行手头上的事情了。
二、调试技术
1、可以使用console对象向javascript控制台写入消息来调试
function sum(num1, num2){ console.log("Enter sum(), arguements are " + num1 + ", " +num2 ); console.log("Before calculation"); var result = num1 + num2; console.log("After calculaation"); console.log("Exiting sum()"); return result; }
2、将消息记录在当前页面
在页面开辟一小块信息,用于显示错误信息
<html> <head> <meta charset = "utf-8"> </head> <body> <script> 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>"; } log("test……"); </script> </body> </html>
3、直接抛出错误
如果错误消息很具体,基本可以把它当做错误来源的依据,那么可以直接抛出错误:
function divide(num1, num2){ if(typeof num1 != "number" || typeof num2 != "number"){ throw new Error("devide (): both arguments must be number."); } return num1 / num2; }
也可以自定义一个assert语句,抛出错误:
//assert接受两个参数,一个是求值结果应该为true的条件,一个是条件为false时需要抛出的错误 function assert(condition , message){ if(!condition){ throw new Error(message); } } function divide(num1, num2){ assert(typeof num1 == "number" && typeof num2 == "number", "devide (): both arguments must be number."); return num1 / num2; }
三、常见的IE的错误
IE是最难调试JAVASCRIPT错误的浏览器,以下介绍一些错误:
1、操作中止
对于IE8之前的版本,在修改尚未加载完的页面时,会发生操作中止错误:
<!doctype html> <html> <head> <title>Operation Aborted Example</title> </head> <body> <p> The following code should cause an Operation Aborted error in IE Versions prior to 8.</p> <div> <script type="text/javascript"> document.body.appendChild(document.createElement("div")); </script> </div> </body> </html>
解决办法可以是不适用appendChild(),而使用insertBefore():
<!doctype html> <html> <head> <title>Operation Aborted Example</title> </head> <body> <p> The following code should cause an Operation Aborted error in IE Versions prior to 8.</p> <div> <script type="text/javascript"> document.body.insertBefore(document.createElement("div"),document.body.firstChild); </script> </div> </body> </html>
也可以把script元素移除来,直接作为<body>的子元素:
<!doctype html> <html> <head> <title>Operation Aborted Example</title> </head> <body> <p> The following code should cause an Operation Aborted error in IE Versions prior to 8.</p> <div> </div> <script type="text/javascript"> document.body.appendChild(document.createElement("div")); </script> </body> </html>
2、无效字符
无效字符是Javascript中没有定义的字符,例如直接从word中赋值文本到编辑器里,然后又在IE中运行,则可能会遇到无效字符的错误。
3、未找到成员
以下函数在单击事件后,window.event对象会被保存;当单击事件执行完毕后,event对象就会被销毁,因而setTimeout中使用的对象就不存在了;因此会出现未找到成员的错误:
document.onclick = function(){ var event = window.event; setTimeout(function(){ event.returnValue = false; //未找到成员函数 },1000); }
4、未知运行时错误
当使用innerHTML或者outerHTML以下列方式操作时会发生错误:1)把块级元素插入到行内元素;2)访问表格的任意部分的任意属性
5、语法错误
6、系统无法找到指定资源
当URL的长度超过IE对URL的最长不能超过2083个字符的限制时,就会发生这个错误:
function createLongUrl(url){ var s = "?"; for(var i = 0, len = 2500; i < len; i++ ){ s += "a"; } return url + s; } var x = new XMLHttpRequest(); x.open("get", createLongUrl("http://www.baidu.com/"), true); x.send(null);