javascript--17错误处理与调试

错误处理与调试
1.开启浏览器错误报告
1.1 Internet Explorer
□Toos → Internet Option → Anvanced → Display a notification about every script error
1.2 Firefox
□Tools → Error Console (Firebug)
1.3 Safari
□Edit → Preferences → Advanced → Show develop menu in menubar/Develop → Show Error Console
1.4 Opera
□Tools → Advanced → Error Console
1.5 Chrome
□Control this page → Developer → JavaScript console
2.错误处理
2.1 Try-catch语句
try{
//可能会导致错误的代码
}catch(error){
//错误发生时怎么处理
}
□错误发生时catch快回收到一个包含错误信息的对象。有一个兼容所有浏览器的message属性。
2.1.1 finally子句
try-catch子句可选,finally子句一经使用,其代码无论如何都会执行。
2.1.2 错误类型
□Error:基类型。主要目的是供开发人员抛出自定义错误。
□EvalError:用eval()函数发生异常时抛出。
□RangeError:数值超出相应范围时触发。
□ReferenceError:找不到对象的情况下
□SyntaxError:把语法错误的JavaScript字符串传入eval()函数。
□TypeError:变量中保存着意外的类型时,或访问不存在的方法时。
□URIError:使用encodeURI()或decodeURI(),而URI格式不正确时。
根据不同的错误类型,进行错误处理:
try{
soemFunction();
}catch(error){
if(error instanceof TypeError){
//处理类型错误
}else if(error instanceof ReferenceError){
//处理引用错误
}else{
//处理其他类型错误
}
}
2.1.3 善用try-catch
□使用try-catch语句,浏览器会认为错误已经被处理。
□使用try-catch语句,最适用吹那些我们无法控制的错误。
□明明白白地知道自己代码发生错误就不该用try-catch而是修复错误。
2.2 抛出错误
①与try-catch语句相配有一个throw操作符。在遇到throw操作符时,代码立即停止执行。仅当有try-catch语句捕获到被抛出的值时,代码才会继续执行。
②throw new Error("something bad happened."); 或利用原型链通过继承Error来创建自定义错误类型。
2.2.1 抛出错误的时机
2.2.2 抛出错误与使用try-catch
2.2.3 错误(error)事件
①任何没有通过try-catch处理的错误都会触发window对象的error事件。
②任何浏览器中,onerror事件处理程序都不会创建event对象。但可接受3个参数:错误消息、错误所在的URL和行号。(只有错误消息有用)
③指定onerror事件处理程序,必须使用DOM0级技术。
window.onerror = function(message,url,line){
alert(message);
return false; //通过返回false,此函数实际上充当了整个文档的try-catch语句可捕获所有无代码处理的运行时错误。
};
④图像也支持error事件。只要图像的src特性中URL不能返回可以被识别的图像格式,就会触发error事件。此时的error事件遵循DOM格式,会返回一个以图像为目标的event对象。
3.错误处理策略
3.1 常见的错误类型
□类型转换错误
□数据类型错误
□通信错误
3.1.1 类型转换错误
类型转换错误发生在使用某个操作符,或者使用其他可能会自动转换值的数据类型的语言结构时。在使用相等(==)和不相等(!==)操作符,或者if、for及while等流控制语句中使用非布尔值时,最常发生类型转换错误。
3.1.2 数据类型错误
在预料之外的值传给函数的情况下,最容易发生数据类型错误。
3.1.3 通信错误
①URL格式不正确或发送的数据有问题。对查询字符串,必须使用encodeURIComponent()方法。
②在服务器响应的数据不正确时,也会发生通信错误。
3.2 区分致命错误和非致命错误
①非致命错误
□不影响用户的主要任务
□只影响页面的一部分
□可以恢复
□重复相同操作可以消除错误
②致命错误
□应用程序根本无法运行
□错误明显影响到了用户的主要操作
□会导致其他连带错误
3.3把错误记录到服务器:(略)
4.调试技术
4.1 将消息记录到控制台
①IE8、Firefox、Chrome和Safari来说,可通过console对象向JavaScript控制台中写入消息。对象有下列方法:
□error(message):将错误消息记录到控制台
□info(message):将信息消息记录到控制台
□log(message):将一般消息记录到控制台
□warn(message):将警告消息记录到控制台
②还有一种方案是使用LiveConnect,也就是JavaScript中运行Java代码。
③向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);
}
}
4.2 将消息记录到当前页面
4.3 抛出错误
①对大型应用程序来说,自定义的错误通常使用assert()函数抛出。对这个函数接受两个参数,一个是求值结果为true的条件,另一个是条件为false时要抛出的错误。
function assert(condition, message){
if(!condition){
throw new Error(message);
}
}
②应用:
function divide(num1,num2){
assert(typeof num1 == "number"&&typeof num2== "number","divide():Both arguments must be numbers.");
return num1/num2;
}
5.常见的IE错误
□操作终止
□无效字符
□未找到成员
□未知运行时错误
□语法错误
□系统无法找到指定资源
下面总结一下JS错误处理与调试的方法
方法1:用alert() 和document.write()方法监视变量值。
alert()在弹出对话框显示变量值的同时,会停止代码的继续运行,直到用户单击“确定”按钮,而document.write()则在输出值后继续运行代码。调试JS时可以根据具体情况来选择这种方法。
例如下面代码:将数组a中以1开头的数据添加到数组b中

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>无标题页</title>
<script type="text/javascript">
var a=["123","456","789","111"];
function AlertMessage()
{
var b=new Array("1111");
for(var i=0;i<a.length;i++)
{
if(a[i].indexOf("1")!=0)
{
alert(a[i]);
b.push(a[i]);
}
}
}
</script>
</head>
<body >
<input type="button" value="点我" onclick="AlertMessage()"/>
</body>
</html>

如果加入的值比较多,则可以使用document.writer()方法,避免反复点击确定按钮。
方法2:用onerror事件找到错误:
当页面出现异常时,error事件会在window对象上触发,它能够在一定程序上告诉开发者出现了错误,并帮助开发者找到错误所在,如下例:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>无标题页</title>
<script type="text/javascript">
window.onerror=function()
{
alert("不好意思,出错了!");
}
</script>
</head>
<body onload="NonExist()" >
</body>
</html>

代码运行body标记的onload事件时调用了一个不存在的函数NonExist(),产生了错误,如下图:

同时,浏览器本身的代码调试错误也出现了: 
要避免浏览器自己的错误提示很简单,只需要要onerror事件的处理函数最后返回ture便可,代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>无标题页</title>
<script type="text/javascript">
window.onerror=function()
{
alert("不好意思,出错了!");
return true;//屏蔽系统事件
}
</script>
</head>
<body onload="NonExist()" >
</body>
</html>

但这样处理对于解决错误并没有任何的帮助。其实onerror还提供了3个参数来确定错误的性质,代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>无标题页</title>
<script type="text/javascript">
window.onerror=function(message,url,line)
{
alert("不好意思,出错了:\n错误提示:"+message+"\nUrl:"+url+"\n行号:"+line);
return true;//屏蔽系统事件
}
</script>
</head>
<body onload="NonExist()" >
</body>
</html>

在IE运行时的提示:

在Firefox运行的提示
 
在IE浏览器中发生error事件时,正常的代码会继续执行,所有的变量和数据都保存下来,并可以通过onerror事件处理函数访问。而在Firefox中,正常的代码执行都会结束,同时所有的错误发生之前的变量和数据都会被销毁.
方法3:用try….catch语句找到错误

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>无标题页</title>
<script type="text/javascript">
try
{
alert("这个是try...catch的例子");
alert(hello);
}
catch(exception)
{
var error="";
for(var i in exception)
{
error+=i+":"+exception[i]+"\n";
}
alert(error);
}
</script>
</head>
<body>
</body>
</html>

IE运行时的提示:
 
Firefox运行时的提示:
 
通过try…..catch可以很轻松的找到错误的问题,不过可惜的是该语句并不能很好地处理语句错误。如下例:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>无标题页</title>
<script type="text/javascript">
try
{
alert("这个是try...catch的例子"));
}
catch(exception)
{
var error="";
for(var i in exception)
{
error+=i+":"+exception[i]+"\n";
}
alert(error);
}
</script>
</head>
<body>
</body>
</html>

try语句里面出现了括号不匹配的错误,而整个代码并没有运行catch中的模块,而是浏览器弹出了错误提示框,如下图:

 
方法4:使用Firefox错误控制台调试:
在Firefox菜单栏中选择“工具”->“错误控制台”,便可以打开它,所有浏览中运行的错误,警告,消息都会传错误控制台,如下:
 
 
Firefox提示的错误信息要比IE全面而且准确的多。
方法5:使用Firefox插件FireBug
Firebug是Firefox下的一款开发类插件,现属于Firefox的五星级强力推荐插件之一。它集HTML查看和编辑、Javascript控制台、网络状况监视器于一体,是开发JavaScript、CSS、HTML和Ajax的得力助手。Firebug如同一把精巧的瑞士军刀,从各个不同的角度剖析Web页面内部的细节层面,给Web开发者带来很大的便利。具体如何安装使用FireBug可参考这篇文章:http://apps.hi.baidu.com/share/detail/15314208
方法6:使用Miscrosoft Script Debugger调试:
在IE菜单栏中打开“工具”->“Internet选项“,选择”高级“,将”禁用脚本调试“复选框的勾去掉。
 
 
 
 
具体如何使用就不介绍了。
方法7:使用IE下的JS调试工具companion.js
一款像firefox中的firedebug工具类似的一个工具包,它的特点就是可以有好的提示错误,并且可以在IE浏览器下方出现控制台输出.方便及时调试。

1、 alert方法
这也是十分原始的方法,但调试起来十分麻烦。
2、 debugger方法
首先打开Internet选项——高级,将“禁用脚本调试(Internet Explorer)”的勾去掉
如果想其他浏览器也启用调试,那么可以把“禁用脚本调试(其他)”的勾也去去掉。
然后在你想需要地方进行调试,就加入debugger,如
<script type="text/javascript">
debugger;
var s="debugger可调试";
alert(s);
</script>
用ie打开该页面,就会出现自动调用VS2005进行调试.
点击是,像平时一样按F10或F11就可以进行调试了

正在或者准备从事javascript编程的人都会使用这个神奇的东西,感到无比自豪。
它几乎可以实现你所想要的任何功能,在不借助任何工具的情况下。
然后,使用过他的人都会知道,这种编程脚本,查询出错或者叫做调试吧,比较麻烦。

下面,我结合自己的一些经验,当然也有一部分自来互联网了。呵呵
1、使用alert函数
这个函数在调试的时候,运用是最多的,针对某个变量或者数组之类的,认为那个地方可能存在问题,就在那个地方alert输出一下,呵呵。
2、使用编辑器的语法高亮功能
针对一些拼写,可能存在错误的地方,使用带有语法高亮功能的编辑器不失为一个好方法,当前有语法高亮功能的编辑器比较多,如editplus、UltraEdit、Dreamweaver等等,如果是在编写代码的时候有关键字(或许准确的保留字吧)拼写错误,就会以不同的颜色给出。
document.write("hello World!");
如果上句中的保留字发生拼写错误,颜色会给出提示,
documents.write("hello World!");
3、注意大小要区分(注意,html是不区分大小写的,但是你的js代码直接写在html里面,就造成了好像要区分大小的现象,这个一定要注意)
在这种脚本语言中是要严格区分大小写的,如果拼写错误,不但颜色不对,还会造成方法错误,不能继续往下执行。
4、括号的配对
这里的括号就包括常用的大括号、小括号,在进行检查的时候这个是一个重点。
5、严格执行代码缩排风格
这个也是相当重要的,特别是在查询错误的时候,当然,你也不能因为这个才保持这种风格了,很会节约时间的。
6、使用浏览器运行调试
其实每一种浏览器都对错误有显示功能,如IE系列、FF等,只是你没有发现而也,这里重点说一下FF的调试功能,特别好用的。
FF自身就有一个错误控制台的功能,开启之后,就会提示错误信息。
当然,最好用的还是要数Web Developer和FireBug插件了,这两个插件的使用方法有很多文章都有介绍。

    一、错误分类
    1、语法错误:也称解析错误,发生在传统语言的编译时,在JavaScript中发生在解释时。这些错误是由代码中的意外字符直接引起的,然后就不能直接编译/解释。发生语法错误时,就不能继续执行代码。在JavaScript中,只有在同一个线程中的代码会受语法错误的影响。在其他线程中的代码和其他外部引用的文件中的代码,如果不依赖于包含错误的代码,则可以继续执行。
    2、运行时错误:也称为异常(exception,在编译期/解释器后)。此时,问题并不出在代码的语法上,而是,尝试完成的一个操作,在某些情况下是非法的。异常只影响发生的线程,其他JavaScript线程即可继续正常的执行。
   
    二、错误处理
    JavaScript提供了两种处理错误的方式:BOM中的onerror事件处理函数方式和ECMAScript中的try...catch方式。
    1、onerror事件处理函数
    它是第一个用来协助JavaScript处理错误的机制。页面上出现异常时,error事件便在window对象上触发。例如:
    复制代码代码如下:
    <html>
    <head>
    <title>onerror Example</title>
    <script type="text/javascript">
    window.onerror = function() {
    alert("发生错误!");
    }
    </script>
    </head>
    <body onload="nonExistentFunction()">
    </body>
    </html>
    在上述代码中,在页面载入时尝试调用不存在的函数,此时会引发一个异常。弹出“发生错误”的错误信息。但是,浏览器的错误信息也显示出来了,如何在浏览器上隐藏它呢,只需onerror方法返回一个true即可。
    复制代码代码如下:
    <script type="text/javascript">
    window.onerror = function() {
    alert(“发生错误!”);
    return true;
    }
    </script>
    1.1 取出错误信息
    onerror处理函数提供了三种信息来确定错误确切的性质:
    i) 错误信息——对于给定错误,浏览器会显示同样的信息
    ii) URL——在哪个文件中发生了错误
    iii) 行号——给定URL中发生错误的行号。
    复制代码代码如下:
    window.onerror = function(sMessage, sUrl, iLine) {
    alert("发生错误!\n" + sMessage + "\nURL:" + sUrl + "\nLine Number:" + iLine);
    return true;
    }
    1.2 图像载入错误
    window对象并非唯一支持onerror事件处理函数的对象,它对图像对象也提供支持。当一个图像由于文件不存在等原因未能成功载入时,error事件便在这个图像上触发。例如:
    复制代码代码如下:
    <img src="noexist.gif" onerror="alert('载入图片时发生错误')"/>
    上例直接在HTML中分配onerror事件处理函数。因为noexist.gif不存在,所以会弹出警告框提示用户。当然也可以通过脚本来分配事件处理函数,在设置图像的src特性前,必须等待页面完全载入,例如:
    复制代码代码如下:
    <html>
    <head>
    <title>Image错误测试</title>
    <script type="text/javascript">
    function handleLoad() {
    document.images[0].onerror = function() {
    alert("载入图片时发生错误!");
    };
    document.images[0].src = "amigo.jpg";
    }
    </script>
    </head>
    <body onload="handleLoad()">
    <img/>
    <body>
    </html>
    注意:与window对象的onerror事件处理函数不同,image的onerror事件没有任何关于额外信息的参数。
    1.3处理语法错误
    onerror事件处理函数不仅可以处理异常,它还能处理语法错误,也只有它才能处理。
    首先,事件处理函数必须是页面中第一个出现的代码,因为如果语法错误出现在设置事件处理函数之前出现,事件处理函数就没有用了。记住,语法错误会完全停止代码的执行。例如:
    复制代码代码如下:
    <html>
    <head>
    <title>onError Example</title>
    <script type="text/javascript">
    alert("Syntax error.";
    window.onerror = function (sMessage, sUrl, iLine){
    alert("An error occurrred:\n" + sMessage + "\nURL:" + sUrl + "\nLine Number:" + iLine );
    return true;
    }
    </script>
    </head>
    <body onload="nonExistentFunction()">
    </body>
    </html>
    因为突出显示的那一行代码(里面有错误语法)在分配onerror事件处理函数之前就出现了,所以浏览器直接报告这个错误。在错误之后的代码就不再被解释(因为这个线程已经退出了),所以 load 事件解发时调用 nonExistentFunction() ,浏览器也会报这个错误。书中说如果重写这个页面,将 onerror 事件处理函数的分配放在语法错误之前,那么会出现两个警告框:一个显示语法错误,另一个显示异常。但我测试的结果还是一样的报两个错误,并不显示onerror事件中的信息。
    使用onerror事件处理函数的主要的问题是,它是BOM的一部分,所以,没有任何标准能控制它的行为。因此,不同的浏览器使用这个事件处理错误的方式有明显的不同,eg,在IE中发生error事件时,正常的代码会继续执行,所有的变量和数据都保留下来,并可通过onerror事件处理函数访问。在Mozilla中,正常的代码执行都会结束,同时所有的错误发生之前的变量和数据都被销毁。
    2、try...catch方式
    ECMPScript第三版,引入了try…catch语句。基本语法如下:
    复制代码代码如下:
    try{
    //code
    [break;]
    } catch ([exception]) {
    //code
    [break;]
    } [finally{
    //code
    }]
    例如:
    复制代码代码如下:
    try {
    window.openFile1();
    alert("成功调用openFile1方法");
    } catch (exception) {
    alert("发生异常!");
    } finally {
    alert("try..catch测试结束!");
    }
    与Java不同,ECMAScript标准在try…catch语句中只能有一个catch语句,因为JavaScript是弱类型的语言,没办法指明catch子句中异常的特定类型。不管错误是什么类型,都由同一个catch语句处理。Mozilla对其进行了扩展,可加多个catch语句,但因为只有 Mozilla 可以使用,因此不推荐使用。
    finally用于包含无论是否有异常发生都要执行的代码,这对关闭打开的链接和释放资源很有用。
    2.1 嵌套 try...catch 语句
    在 try...catch 语句中的 catch 子句中,也会发生错误。此时,就可以使用嵌套的 try...catch 语句。示例:
    复制代码代码如下:
    try {
    eval("a ++ b");
    } catch(oException) {
    alert("发生错误!");
    try {
    var aError = new Array(1000000000000000000000000000000000000000);
    } catch(exception) {
    alert("在catch子句中发生错误!");
    }
    } finally{
    alert("已完成")
    }
    2.2 Error对象
    发生错误时,JavaScript有个Error基类用于抛出。它有两个特性:
    i)name——表示错误类型的字符串
    ii)message——实际的错误信息
    Error对象的name对应于它的类,可以是如下值之一:
    EvalError:错误发生在eval()函数中;
    RangeError:数字值超出JavaScript可表示的范围;
    ReferenceError:使用了非法的引用;
    SyntaxError:在eval()函数调用中发生了语法错误,其他的愈发错误由浏览器报告,无法通过try…catch处理;
    TypeError:变量的类型不是预期所需的;
    URIError:在encodeURI或decodeURI函数发生了错误。
    2.3 判断错误类型
    尽管每个 try...catch 语句中只能有一个catch子句,但判断抛出的错误类型方法主要有两种。第一种使用 Error 对象的 name 特性:
    复制代码代码如下:
    try {
    eval("a ++ b");
    } catch(oException) {
    if (oException.name = "SyntaxError") {
    alert("发生SyntaxError!");
    } else {
    alert("发生其他错误!");
    }
    }
    第二种使用 instanceof 操作符,并使用不同错误的类名:
    复制代码代码如下:
    try {
    eval("a ++ b");
    } catch(oException) {
    if (oException instanceof SyntaxError) {
    alert("发生SyntaxError!");
    } else {
    alert("发生其他错误!");
    }
    }
    2.4 抛出异常
    在ECMAScript第三版引入,用于有目的的抛出异常,抛出的错误对象可为字符串、数字、布尔值或实际的对象,也可以抛出Error对象(其构造函数只有一个函数,即错误信息)。如:
    复制代码代码如下:
    throw new Error("错误产生!");
    开发人员抛出的错误和由浏览器自身抛出的错误都在 try...catch 中捕获。例如:
    复制代码代码如下:
    function addTwoNumber(a, b) {
    if (arguments.length < 2) {
    throw new Error("需要传入两个数字!");
    }
    }
    try {
    result = addTwoNumber(90);
    } catch(oException) {
    if (oException instanceof SyntaxError) {
    alert("SyntaxError:" + oException.message);
    } else if (oException instanceof Error){
    alert(oException.message);
    }
    }
    三、调试技巧
   
    现在的浏览器大多都自带了调试工具,大多数情况下已经够用了,另外IE下还可以用IETest,FireFox下还可以用FireBug。

17.4.1 操作终止
在IE8 之前的版本中,存在一个相对于其他浏览器而言,最令人迷惑、讨厌,也最难于调试的错误:操作终止(operation aborted)。在修改尚未加载完成的页面时,就会发生操作终止错误。发生错误时,会出现一个模态对话框,告诉你“操作终止。"单击确定(OK) 按钮,则卸载整个页面,继而显示一张空白屏幕;此时要进行调试非常困难。下面的示例将会导致操作终止错误。

body
    div
        script
            document.body.appendChild(document.createElement("div"));
        script
    div
body
这个例子中存在的问题是:JavaScript代码在页面尚未加载完毕时就要修改document.body,而且script元素还不是body元素的直接子元素。准确一点说,当script节点被包含在某个元素中,而且JavaScript代码又要使用appendChi1d、innerHTML或其他DOM 方法修改该元素的父元素或祖先元素时,将会发生操作终止错误(因为只能修改已经加载完毕的元素)。

要避免这个问题,可以等到目标元素加载完毕后再对它进行操作,或者使用其他操作方法。例如,为document.body添加一个绝对定位在页面上的覆盖层,就是一种非常常见的操作。通常,开发人员都是使用appendChild方法来添加这个元素的,但换成使用insertBefore()方法也很容易。因此,只要修改前面例子中的一行代码,就可以避免操作终止错误。

body
    div
        script
            document.body.lnsertBefore(document.createElement("div"), document.body.firstChild);
        script
    div
body
在这个例子中,新的div元素被添加至document.body的开头部分而不是末尾。因为完成这一操作所需的所有信息在脚本运行时都是已知的,所以这不会引发错误。

除了改变方法之外,还可以把script元素从包含元素中移出来,直接作为body的子元素。例如:

body
    div
    div
    script
        document.body.appendChild(document.createElement("div"));
    script
body
这一次也不会发生错误,因为脚本修改的是它的直接父元素,而不再是间接的祖先元素。

在同样的情况下,IE8不再抛出操作终止错误,而是抛出常规的JavaScript 错误,带有如下错误消息:

HTML Parsing Error: unable to modify the parent container element before the child element is closed (KB927917).

不过,虽然浏览器抛出的错误不同,但解决方案仍然是一样的。


17.4.2 无效字符
根据语法,JavaScript 文件必须只包含特定的字符。在JavaScript 文件中存在无效字符时, IE会抛出无效字符( invalid character )错误。所谓无效字符,就是JavaScript语法中未定义的字符。例如,有一个很像减号但却由Unicode 值8211 表示的字符( \u2013 ),就不能用作常规的减号( ASCII 编码为45 ),因为JavaScript 语法中没有定义该字符。这个字符通常是在Word 文档中自动插入的。如果你的代码是从Word 文档中复制到文本编辑器中,然后又在IE 中运行的,那么就可能会遇到无效字符错误。其他浏览器对无效字符做出的反应与IE类似,Firefox会抛出非法字符(iIlegal character) 错误,Safari会报告发生了语法错误,而Opera 则会报告发生了ReferenceError (引用错误)。因为它会将无效字符解释为未定义的标识符。

17.4.3 未找到成员
IE中的所有DOM对象都是以COM 对象,而非原生JavaScript对象的形式实现的。这会导致一些与垃圾收集相关的非常奇怪的行为。IE中的未找到成员( Member not found )错误,就是由于垃圾收集例程配合错误所直接导致的。

具体来说,如果在对象被销毁之后,又给该对象赋值,就会导致未找到成员错误。而导致这个错误的,一定是COM 对象。发生这个错误的最常见情形是使用event 对象的时候。IE中的event对象是window的属性,该对象在事件发生时创建,在最后一个事件处理程序执行完毕后销毁。假设你在一个闭包中使用了event 对象,而该闭包不会立即执行,那么在将来调用它并给event 的属性赋值时,就会导致未找到成员错误,如下面的例子所示。

document.onclick = function () {
    var event = window.event;
    setTimeout(function (){
        event.returnValue = false;  //未找到成员错误
    }, 1000);
};
在这段代码中,我们将一个单击事件处理程序指定给了文档。在事件处理程序中,window.event被保存在event 变量中。然后,传人setTimeout()中的闭包里又包含了event变量。当单击事件处理程序执行完毕后,event 对象就会被销毁,因而闭包中引用对象的成员就成了不存在的了。换句话说,由于不能在COM对象被销毁之后再给其成员赋值,在闭包中给returnValue 赋值就会导致未找到成员错误。

17.4.4 未知运行时错误
当使用innerHTML或outerHTML以下列方式指定HTML时,就会发生未知运行时错误( Unknown runtime error ):一是把块元素插入到行内元素时, 二是访问表格任意部分( table 、 tbody等)的任意属性时。例如,从技术角度说,span标签不能包含div之类的块级元素,因此下面的代码就会导致未知运行时错误:

span.innerHTML = "div Hi /div";  //这里,span包含了div元素
在遇到把块级元素插入到不恰当位置的情况时,其他浏览器会尝试纠正并隐藏错误,而IE在这一点上反倒很较真儿。

17.4.5 语法错误
通常,只要IE一报告发生了语法错误( syntax error ),都可以很快找到错误的原因。这时候,原因可能是代码中少了一个分号,或者花括号前后不对应。然而,还有一种原因不十分明显的情况需要格外注意。

如果你引用了外部的JavaScript 文件,而该文件最终并没有返回JavaScript代码,IE也会抛出语法错误。例如,script元素的src特性指向了一个HTML文件,就会导致语法错误。报告语法错误的位置时,通常都会说该错误位于脚本第一行的第一个字符处。Opera 和Safari 也会报告语法错误,但它们会给出导致问题的外部文件的信息;IE就不会给出这个信息,因此就需要我们自己重复检查一遍引用的外部JavaScript文件。但Firefox会忽略那些被当作JavaScript 内容嵌入到文档中的非JavaScript文件中的解析错误。

在服务器端组件动态生成JavaScript 的情况下,比较容易出现这种错误。很多服务器端语言都会在发生运行错误时,向输出中插入HTML代码,而这种包含HTML的输出很容易就会违反JavaScript语法。如果在追查语法错误时遇到了麻烦,我们建议你再仔细检查一遍引用的外部文件,确保这些文件中没有包含服务器因错误而插入到其中的HTML。

17.4.6 系统无法找到指定资源
系统无法找到指定资源(The system cannot locate the resource specified )这种说法,恐陷要算是IE给出的最有价值的错误消息了。在使用JavaScript 请求某个资源URL ,而该URL的长度超过了IE 对URL最长不能超过2083个字符的限制时,就会发生这个错误。IE不仅限制JavaScript中使用的URL的长度,而且也限制用户在浏览器自身中使用的URL长度(其他浏览器对URL 的限制没有这么严格)。IE 对URL路径还有一个不能超过2048个字符的限制。下面的代码将会导致错误。

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.somedomain.com/"), true);
x.send(null);
在这个例子中,XMLHttpRequest对象试图向一个超出最大长度限制的URL发送请求。在调用open()方法时,就会发生错误。避免这个问题的办法,无非就是通过给查询字符参数起更短的名字,或者减少不必要的数据,来缩短查询字符串的长度。另外,还可以把请求方法改为POST,通过请求体而不是查询字符串来发送数据。












猜你喜欢

转载自zhyp29.iteye.com/blog/2304521