Javascript 内存泄漏问题
2007-12-11 18:38
内存泄漏,就是内存不能够被正确地配置,内存不能及时有效回收,他会导致程序执行效率降低甚至执行失败。

在浏览器领域,大部分都可能会出现内存泄漏问题,但是以IE最为多见,也最为严重,尤其是页面中有许多Javascript的交互效果的时候。其中涉及到循环结构(cyclic structure)DOM对象属性、JavaScript对象属性以及垃圾回收器garbage collector

循环结构(cyclic structure),是指一个DOM对象包含JavaScript对象参数(事件处理函数),JavaScript对象又包含了DOM对象的属性参数。(比如给某个超链接A添加一个onclick事件函数,这时候A就有了相应的事件处理函数,而JavaScript函数对象中也有了A的onclick属性)。

当循环结构(cyclic structure)形成时如果没有别的参数传递给DOM对象或者Javascript函数对象,JavaScript的垃圾回收器(一个自动内存管理器)就会把这两个对象的内存释放并重新进行配置,但是IE的DOM对象属性参数并不能由JavaScript管理清除(不能清除DOM对象的属性参数),而他自己的内存管理机制并不能理解循环结构(cyclic structure)的垃圾回收机制。因此,当循环结构(cyclic structure)的垃圾回收条件形成时,IE也不能进行正确的内存回收管理,导致内存泄漏。当然,这只有在循环结构的未回收内存的数量达到很大的数量级的时候,才会出现明显的内存泄漏症状。

此外,由于循环结构在闭包中出现的几率较大,内存泄漏问题也是不可忽视的。

解决的办法有:

一、避免让可能被移除或改变的DOM对象(remove node/reset innerHTML)中出现循环结构(cyclic structure);

二、在DOM对象被移除前(remove node/reset innerHTML)清空他的属性参数(domNode.Jsfunction = null)

1.避免扩展DOM对象的属性参数,如果有要在适当的时候清空;
2.如果某个事件处理函数在移除后可能被某些DOM对象调用,一定要清空;
3.Ajax中XMLHttpRequest的onreadystatechange事件函数调用之后要清。
4....


以上纯属个人理解,大家自行辨解,同时还望各位高手不吝赐教。


一个可以清除某个DOM对象及其子孙对象的事件属性的函数
function purge(d) {
    var a = d.attributes;//取得DOM对象的所有事件属性
    if (a) {
        var l = a.length;
        for ( var i = 0; i < l; i += 1) {
            var n = a[i].name;//取得DOM对象事件属性的名称如onclick、onblur等
            if (typeof d[n] === 'function') {
                d[n] = null;//清空DOM对象事件属性的值
            }
        }
    }
    a = d.childNodes;//处理子元素
    if (a) {
        l = a.length;
        for (i = 0; i < l; i += 1) {
            purge(d.childNodes[i]);
        }
}
}


Douglas Crockford: JScript Memory Leaks
http://www.crockford.com/javascript/memory/leak.html

Justin Rogers: Understanding and Solving Internet Explorer Leak Patterns
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp
posted on 2008-05-30 09:11  Liu Jian  阅读(559)  评论(0编辑  收藏  举报