jquery ie6内存泄露innerHTML使用注意
来源:互联网 发布:小二黑结婚知乎 编辑:程序博客网 时间:2024/04/30 01:19
问题代码:
首先看下面一段代码:
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html>
- <head>
- <meta content="text/html;charset=utf-8" http-equiv="content-type" />
- <script src="jquery-1.3.2.js" type="text/javascript">
- </script>
- <style type="text/css">
- #inner {
- margin:0 auto;
- width:150px;
- height:50px;
- border:1px solid green;
- }
- </style>
- <script type="text/javascript">
- $(function(){
- $("#inner").click(function(){
- //错误,引起内存泄露
- $("#test")[0].innerHTML="";
- //正确做法
- //$("#test").empty();
- });
- });
- </script>
- <title>测试</title>
- </head>
- <body>
- <div style="height:500px;width:500px;border:1px solid red;padding-top:100px;" id="test">
- <div id="inner">click to remove me</div>
- </div>
- </body>
- </html>
场景:
inner div 就是常见的我们可能使用 ajax 从服务器动态构造的元素,或者注入的片断html,效果为点击 inner 后就把它以及它的兄弟清除出去,依照传统的思路,直接 innerHTML =“” 就好了 ,可能你会想到所有删除元素的事件监听器应该清楚掉,但是对于除了 ie6 (引起内存泄露)以外的浏览器,清除事件监听器不是必要的 。
jquery 机制:
但是可以确定的是在 jquery 中用 innerHTML 的方法来清空元素,是必然会导致内存泄露的,由于 jquery 对于同一元素多事件处理没有直接采用浏览器事件模型,而是自己缓存事件,遍历触发,以及便于 trigger 程序触发 :
- // Init the element's event structure
- var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
- handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
- // Handle the second event of a trigger and when
- // an event is called after a page has unloaded
- return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
- jQuery.event.handle.apply(arguments.callee.elem, arguments) :
- undefined;
- });
采用 data 方法,将一些数据关联到了元素上面,上述事件即是采用该机制缓存事件监听器。
那么就可以知道,直接 innerHTML=“” 而不通知 jquery 清空与将要删除元素关联的数据,那么这部分数据就再也释放不了了,即为内存泄露。
解决:
jquery 已经想到了这一方面,提供了 empty 函数,其思想就是,对节点的所有子,孙,重孙.....节点( $("*",this) ),先清空它们关联的数据,再进行节点的删除:
- remove: function( selector ) {
- if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
- // Prevent memory leaks
- jQuery( "*", this ).add([this]).each(function(){
- jQuery.event.remove(this);
- jQuery.removeData(this);
- });
- if (this.parentNode)
- this.parentNode.removeChild( this );
- }
- },
- empty: function() {
- // Remove element nodes and prevent memory leaks
- jQuery(this).children().remove();
- // Remove any remaining nodes
- while ( this.firstChild )
- this.removeChild( this.firstChild );
- }
jquery导致IE6崩溃的继续研究
经过一系列的测试,我认为,jquery可能存在较严重的,导致浏览器崩溃的BUG
事件经过
1. 我在一个项目中引用了jquery,多数都是用于ajax请求的,在IE6会导致浏览器崩溃(IE7不会,经过10台以上计算机的测试,都存在,不是个别现象),初步认为是jquery的ajax并发导致的
2. 使用我以前封装的ajax类(也是应用于项目过的),同样会有这个问题,排除ajax问题。
3. 在网上发现,js内存溢出和窗口句柄的占用可能导致IE崩溃,于是重写方法,使用对象化,并在最后清除内存,还是会崩溃。
4. 最后,不使用任何jquery方法,采用原始的javascript,没有再崩溃了。。。。
使用的是jquery 1.1.2 pack版,已验证,源码版和pack版都有这样的问题,尚未验证1.1.1版有没有这个问题。
附件是测试的demo,经过简化处理,数据是读取的xml。
calendar_OOP_Jquery.htm 采用对象化的js,使用了jquery。不出10次就会崩溃
calendar_noOOP_Jquery.htm 使用jquery。不出10次就会崩溃
calendar_noOOP_noJquery.htm 没有采用面向对象js,没有使用jquery。测试到300次没有崩溃
日历算法的代码可以无偿使用、传播和修改,如果发现有什么BUG,请和我联系cimmicola#163.com
我实在是无语了。仅仅是使用了$选择器和html()方法。
如何避免JQuery Dialog的内存泄露
Posted on 2010-06-18 17:18 Kevin-moon 阅读(1667) 评论(8) 编辑 收藏 所属分类: Web前端技术autoOpen: false,
width: 600,
buttons: {
"Ok": function() {
$(this).dialog("close");
},
"Cancel": function() {
$(this).dialog("close");
}
}
});
在一些JS交互性不多的一般页面来说,没有任何问题!但是对于交互性强的,需要动态加载与释放DOM的页面来说,它就是一个悲剧的东西!为什么这样说?大家看下下面的例子:
一段简单的代码,一个DIV是通过动态加载到页面上,然后对该DIV用Dialog进行绑定,以达到弹出的目的!下面的test元素就是<div id="test"></div>。
$("#test").append('<div id="dialog"><div id="fileQueue"></div> <input type="file" name="uploadify" id="uploadify" />' +
'<a href="javascript:upload();">上传</a>' +
'<a href="javascript:$(#uploadify).uploadifyClearQueue()">取消上传</a><div>');
$('#dialog').dialog({
autoOpen: false,
width: 600,
buttons: {
"Ok": function() {
$(this).dialog("close");
},
"Cancel": function() {
$(this).dialog("close");
}
}
});
return false;
}
接着,我需要删除该DOM元素,一般来说,正常的做法都是$("#test").empty();这行简单的代码就完成了!这样有效吗?!当执行完这样代码后,你再用$('#dialog')来获取dialog元素,郁闷的事情发生了,既然获取到了!为什么!不是已经empty了吗!
下面我们来看下这一悲剧是如何造成的,
我们把注意点放到$('#dialog').dialog上面,然后看看JQuery的实现代码是如何写的,当我们跟踪代码到dialog类中的_create方法的时候,问题的原因找到了,看下面这段代码:
.appendTo(document.body)
.hide()
.addClass(uiDialogClasses + options.dialogClass)
.css({
zIndex: options.zIndex
})
// setting tabIndex makes the div focusable
// setting outline to 0 prevents a border on focus in Mozilla
.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
if (options.closeOnEscape && event.keyCode &&
event.keyCode === $.ui.keyCode.ESCAPE) {
self.close(event);
event.preventDefault();
}
})
.attr({
role: 'dialog',
'aria-labelledby': titleId
})
.mousedown(function(event) {
self.moveToTop(false, event);
}),
它既然也动态创建一个div,而且把该div加到了Body上面,然后把dialog中的元素从<div id=test>中移除,加入到该新的div中.....
这就是为什么我们$("#test").empty()后,却对内部的dialog没有起作用了!而且这有一个最不好的一个地方,也是最容易出现内存泄露的地方:它动态的在Body中创建了一个div,这样如果窗体不关闭的话,而你又在不察觉的情况下不断的使用上面的TestAppend方法来动态加载DOM,就会创建N个这样的div!
其实这个问题郁闷的地方不是在如何解决,而且隐藏的很深,很难发现!那么发现之后解决起来就变的简单多了:
$('#dialog').parent().empty();
$('#dialog').parent().remove();
}
当前加上这段后代码后,再做$("#dialog")来测试下,期望的结果终于出现了!dialog元素消失了!
Jquery1.3的在ie6下ajax缺陷
文章分类:Web前端- xhr:function()
- {
- return window.activexobject ? new activexobject("microsoft.xmlhttp") : new xmlhttprequest();
- }
直接崩溃掉,从上篇文章中了解到,microsoft.xmlhttp为ie下最早的一个xmlhttp版本,看来jquery的开发者也有意的将ie6系列的浏览器抛弃
ie7 已经开始支持xmlhttprequest.
最后将这段代码改写成如下模样
- var orequest;
- if(typeof xmlhttprequest=="undefined" && window.activexobject)
- {
- var arrsignatures = ["msxml2.xmlhttp.5.0","msxml2.xmlhttp.4.0","msxml2.xmlhttp.3.0","msxml2.xmlhttp","microsoft.xmlhttp"];
- for(var i=0;i<arrsignatures.length;i++)
- {
- try
- {
- orequest = new activexobject(arrsignatures[i]);
- return orequest;
- }
- catch(oerror)
- {
- }
- }
- }
- else
- orequest=new xmlhttprequest();
- return orequest
- jquery ie6内存泄露innerHTML使用注意
- jquery ie6内存泄露innerHTML使用注意
- jquery innerHTML使用注意
- 偶遇IE6内存 泄露
- jquery 如何使用innerHTML
- jquery 使用innerHTML
- jquery 如何使用innerHTML
- JNI使用注意与避免内存泄露总结
- sigsetjmp siglongjmp使用时要注意内存泄露
- 在使用lua的tolua的内存泄露注意
- Android内存泄露检测LeakCanary使用注意点
- JQuery内存泄露解决办法
- C++内存泄露注意点
- C++内存泄露注意点
- 解决ie6内存泄露的问题
- 解决IE6内存泄露的另类方法
- innerHTML使用总结4个注意点
- 内存泄露检测工具使用
- 《Linux内核修炼之道》之高效学习linux驱动开发
- 复制文章自动copy文章地址以及版权的JS
- JRE、JDK和SDK分别是什么
- 窗体返回
- Linux中put_user和memcpy的区别
- jquery ie6内存泄露innerHTML使用注意
- js实现点击复制本页标题,地址的代码
- Modbus Master & Slave of WinCE on X86
- Java2Word API
- 爱Android更要懂Android
- ARM BL或中断返回需要注意的一些细节问题
- JQuery 常用方法基础教程
- 根文件系统中相关配置文件的介绍
- javascript十个最常用的自定义函数