整理一下常见的IE错误


Posted in Javascript onNovember 18, 2016

多年以来,IE一直都是最难于调试JavaScript 错误的浏览器。IE给出的错误消息一般很短又语焉不详。而且上下文信息也很少,有时甚至一点都没有。下面几小节将分别探讨一些在IE中难于调试的JavaScript 错误。

操作终止

在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).

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

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

未找到成员
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 赋值就会导致未找到成员错误。

未知运行时错误

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

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

语法错误

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

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

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

系统无法找到指定资源
系统无法找到指定资源(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,通过请求体而不是查询字符串来发送数据。

Javascript 相关文章推荐
js根据给定的日期计算当月有多少天实现思路及代码
Feb 25 Javascript
JS Jquery 遍历,筛选页面元素 自动完成(实现代码)
Jul 08 Javascript
AngularJs表单验证实例详解
May 30 Javascript
强大Vue.js组件浅析
Sep 12 Javascript
jQuery实现右键菜单、遮罩等效果代码
Sep 27 Javascript
Node.js与MySQL交互操作及其注意事项
Oct 05 Javascript
预防网页挂马的方法总结
Nov 03 Javascript
Angular2+国际化方案(ngx-translate)的示例代码
Aug 23 Javascript
详解wow.js中各种特效对应的类名
Sep 13 Javascript
Vue.js 2.0和Cordova开发webApp环境搭建方法
Feb 26 Javascript
如何用input标签和jquery实现多图片的上传和回显功能
May 16 jQuery
JavaScript中while循环的基础使用教程
Aug 11 Javascript
require、backbone等重构手机图片查看器
Nov 17 #Javascript
基于touch.js手势库+zepto.js插件开发图片查看器(滑动、缩放、双击缩放)
Nov 17 #Javascript
移动端js图片查看器
Nov 17 #Javascript
javascript另类方法实现htmlencode()与htmldecode()函数实例分析
Nov 17 #Javascript
JavaScript实现解析INI文件内容的方法
Nov 17 #Javascript
详解AngularJS中的表单验证(推荐)
Nov 17 #Javascript
JavaScript实现清空(重置)文件类型INPUT元素值的方法
Nov 17 #Javascript
You might like
用libTemplate实现静态网页的生成
2006/10/09 PHP
phpMyAdmin 链接表的附加功能尚未激活的问题
2010/08/01 PHP
laravel5创建service provider和facade的方法详解
2016/07/26 PHP
PHP入门教程之字符串处理技巧总结(转换,过滤,解析,查找,截取,替换等)
2016/09/11 PHP
cakephp2.X多表联合查询join及使用分页查询的方法
2017/02/23 PHP
Yii2中添加全局函数的方法分析
2017/05/04 PHP
php判断文件上传图片格式的实例详解
2017/09/30 PHP
IE DOM实现存在的部分问题及解决方法
2009/07/25 Javascript
关于JavaScript定义类和对象的几种方式
2010/11/09 Javascript
浅析jQuery的链式调用之each函数
2010/12/03 Javascript
js 关键词高亮(根据ID/tag高亮关键字)案例介绍
2013/01/21 Javascript
jquery获取一个元素下面相同子元素的个数代码
2014/07/31 Javascript
Javascript验证用户输入URL地址是否为空及格式是否正确
2014/10/09 Javascript
js动态修改表格行colspan列跨度的方法
2015/03/30 Javascript
jQuery垂直多级导航菜单代码分享
2015/08/18 Javascript
AngularJs实现ng1.3+表单验证
2015/12/10 Javascript
js判断移动端是否安装某款app的多种方法
2015/12/18 Javascript
jQuery插件实现图片轮播特效
2016/06/16 Javascript
微信小程序 时间格式化(util.formatTime(new Date))详解
2016/11/16 Javascript
Javascript中toFixed计算错误(依赖银行家舍入法的缺陷)解决方法
2017/08/22 Javascript
微信小程序基于Taro的分享图片功能实践详解
2019/07/12 Javascript
java遇到微信小程序 &quot;支付验证签名失败&quot; 问题解决
2019/12/22 Javascript
[01:29:31]VP VS VG Supermajor小组赛胜者组第二轮 BO3第一场 6.2
2018/06/03 DOTA
python中的sort方法使用详解
2014/07/25 Python
Python中的fileinput模块的简单实用示例
2015/07/09 Python
Python实现二维曲线拟合的方法
2018/12/29 Python
Python理解递归的方法总结
2019/01/28 Python
python滑块验证码的破解实现
2019/11/10 Python
Python3如何在Windows和Linux上打包
2020/02/25 Python
小学生防溺水广播稿
2014/01/12 职场文书
信息总监管理职责范本
2014/03/08 职场文书
大二学生学年自我鉴定
2014/09/12 职场文书
缓刑期间思想汇报范文
2014/10/10 职场文书
记者节感言
2015/08/03 职场文书
《海上日出》教学反思
2016/02/23 职场文书
Python机器学习之KNN近邻算法
2021/05/14 Python