首先声明, 这事我也有责任!!!!
对IE的内存泄露 和IE的内存回收 以及IE7的不思进取了解的不够!!!

我印象中 下面三件事能够引起IE臭名昭著的内存问题

1 dom和js对象彼此之间不恰当的引用
以及
2 给dom结点添加事件
还有
3 反复的对dom进行innerHTML操作


以上三点都有可能引起内存泄露或者是内存无法回收.

所以我在开发时极力避免了上面情况的发生.而且我是在IE7下进行开发和测试.

当我避免了上面的三种错误, 而且在IE7下测试,依然产生大量的孤立dom结点时
我就不得不怀疑我的程序存在严重问题了. 于是我开始看啊 找啊 分析啊 调试啊

GT grid的几千行代码不停的改着测着 但是我就是没找到原因 而且代码被我弄得面目全非,依然没有找到原因.

周日发布最新demo版的计划也要暂时搁浅了


不过 我真的很努力了 希望大家相信我 也继续支持我


先不给自己的再次食言找接口了 继续我的那个问题. 后来自己写了一个简单的页面. 一个避免了上面提到的三点 而且足够简单的页面


<html>
 <head>
<script type="text/javascript">

function $(id) {
	return typeof(id)=='string'?document.getElementById(id):id;
}

function removeElement(el){
		el=$(el);
		if (el && el.parentNode) {
			el.parentNode.removeChild(el);
		}
}

  </script>
 </head>

 <body >
  <div id="ttt">aaa</div>

  <input type="button" value="b1" onclick="removeElement('ttt')">
 </body>
</html>


原来ie的 removeChild 也有问题 . 其实EXT已经提供了一个相对好的解决方案

大家看看ext的做法:


        removeNode : isIE ? function(){
            var d;
            return function(n){
                if(n && n.tagName != 'BODY'){
                    d = d || document.createElement('div');
                    d.appendChild(n);
                    d.innerHTML = '';
                }
            }
        }() : function(n){
            if(n && n.parentNode && n.tagName != 'BODY'){
                n.parentNode.removeChild(n);
            }
        },


唉 都怪我学习他人代码的时候不够认真仔细 看来还要继续努力了.
不过 ext这种做法真的就是最好的吗?? 还有没有更好的呢??


====================================
经过hax的提示 又做了测试 果然有更好的办法

那就是在 利用ie下的 outerHTML="" 方法.

另外关于 ie 的 removeNode方法测试了

当使用 el.removeNode() 时 可以清除el 同时内存会回收
但是 大家注意 这时候由于没有指定 删除子结点 (removeNode的参数)
所以子结点不会被删除
于是我加上了参数 el,removeNode(true)

奇怪的事情发生了 此时不好用了 el和el的子结点都没有被回收

这样看来 removeNode 就没什么意义了

====================================
但是 经过进一部确认 最好的做法还是 ext的做法

因为不是所有的元素都可以执行 outerHTML="" 这个操作的
因为和innerHTML一样 对于有些元素来说 outerHTML这个属性是只读的

呵呵

这么一个小问题 我也要研究这么半天 唉 看来基础知识还需要加强啊
评论
oznyang 2008-04-08
发现在ie下
var div=document.getElementById('aa');
div.parentNode.removeChild(div);
div.removeNode();
就能释放掉aa这个div了
hax 2008-03-17
ms的论坛上对此问题的帖子:http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2840253&SiteID=1

从这个帖子里可以补充这样2点:

1. 递归的removeChild貌似可以解决问题?那么也就是说,之所以没有被回收,是因为下面这些node之间存在引用?
2. 注意事件handler会阻止回收,所以要先清干净。
DavidL 2008-03-17
基于垃圾的设计只能写出垃圾的代码,垃圾的代码只能产生垃圾的结果。不是楼主水平不济,从楼主的研究来看钻研精神可嘉,结果也不错,但是。。怎么说呢,非要在IE上搞个你死我活还真的累啊!就好像写一个应用程序一定要你用ASM写一样恶心。。
可是目前又不能不搞IE的咚咚,我深切同情着楼主的遭遇
fins 2008-03-17
回 playfish :


ie developer toolbar
script editor (微软的那个 office里带)
companion js


不过这些也只是我知道的,但是不常用 因为都没有firebug好用
我一般保证编写的代码跨浏览器 支持ff 这样只用firebug就好了

在IE下只用下面这个来帮助我分析和解决一些ie下的问题:

drip,可以查看dom结点和内存的使用情况
我稍后写篇文章详细介绍一下它的一个加强版本
fins 2008-03-17
回 cats_tiger

内存泄露的话 刷新页面也不会回收
内存泄露很容易避免, 但是IE还有一个问题,就是我主贴中提到的
不泄露 但是内存无法回收(刷新页面可以回收)
这种问题往往更难处理
playfish 2008-03-17
我也很想提问一个问题。。您开发js是用什么来测试的?我在firefox下用firebug调试,但是在IE下找不到一个好的东西来测试。。
cats_tiger 2008-03-16
提几个个非常非常白痴+外行的问题,IE中纯JS的组件内存泄漏会带来哪些影响呢?如果我刷新页面,IE会正确的释放内存吗?最重要的是,内存的泄漏会给使用者带来哪些不便呢?
hax 2008-03-16
我只是猜测有其他方法,fins同志倒是很认真的测试了。不过,从你的测试结果来看,我建议你再试试看,先使用innerHTML清空node的所有子节点,然后node.removeNode()。

BTW,这种问题归根到底只是IE造成的,并不是我们开发者的责任。我倒是期望不要再有机会去加强这类“基础知识”……
fins 2008-03-16
已经更新主楼
fins 2008-03-16
谢谢 hax兄

刚才我自己测试了一下
结果是非常让人意外的

稍后发上来
hax 2008-03-16
ie的问题就是,不会回收被remove的node,虽然这个node已经没有任何js对象在直接或间接的引用到它。对应的解决方案就是把node扔到一个div里(嘿嘿,这个div就是ie的垃圾回收箱),然后把其innerHTML清空。

当然,按照MS的人的说法,这个不是一个真正的memory leak,因为你刷新页面时是会释放这些对象的。但是ajax程序如果是长时间驻留在一个页面,并且动态增删许多节点,那累积起来的结果确实够惨。

至于有没有其他方法呢?我猜是有的。但是需要测试来证明其可行。一个方法是outerHTML直接删。另一个方法是试试看ie自己的removeNode方法。注意,这些是我的猜测,需要测试才能知道能否奏效。
发表评论

您还没有登录,请登录后发表评论