Js内存泄露问题总结

最近接受了一个Js职位的面试,问了不少Js的高级特性,才发现长时间使用已知的特性进行开发而忽略了对这门语言按部就班的理解,包括Java我想也是同样,偶尔在Sun官方看到JDK6.0列举出来的new features才发现不少东西是本身并不知道或者遗忘了的。看来仍是要坚持总结技术,反复理解和运用才能保持对任何技术的掌握运用能力阿。

翻了一些Js的新老资料,准备先讲讲Js的内存泄露问题——
当一个DOM对象包含一个Js对象的引用(例如一个Event Handler), 而这个Js对象又持有对这个DOM对象的引用时,一个环状引用就行成了。这自己并非什么错误或者Bug,由于Js的回收机制能理解这种环状的引用结构而且在没有其余对象能关联到环上的时候回收这个环上的全部对象内存。可不幸的是IE浏览器中的DOM结构并不受Js解释机制管理,因此它并不能理解这种失去外界引用的环状结构,致使环上任何对象都没法被访问到,但是内存依旧占据着,这也就是所谓的Js内存泄露了。

咱们来看一个经典的例子说明问题——程序员

JScript code

(function(limit, delay){
var queue=new Array(10);
var n;
function makeSpan(n){
    var s=document.createElement(‘span’);
    document.body.appendChild(s);
    var t=document.createTextNode(‘ ’+n);
    s.appendChild(t);
    s.onclick=function(e){
    s.style.backgroundColor=’red’;
alert(n);
};
return s;
}

function process(n){
    queue.push(makeSpan(n));
    var s=queue.shift();
    if(s)
        s.parentNode.removeChild(s);
}

function loop()}{
    if(n<limit){
    process(n);
    n+=1;
    setTimeout(loop,delay);
}
}
loop();
})(10000,10);web

 

这个例子的意义是建立出10000个span元素来添加到DOM的body上,而且对其内容填充序号n,紧接着从queue的第一个位置移除建立的span元素,也就是说10000个为止,不断的建立再移除,永远只保留最新建立的那10个。这个例子知足的条件就是DOM元素带有Js对象即click事件的Event Handler,而Event Handler里面又带有这个DOM元素的引用,因而环状结构行程。

当我在IE上运行这个Js的时候打开任务管理器,很明显的看到此网页的内存从55M左右起很稳定的增加直到结束第10000个span建立完毕中止增加时已经到了167M,而在Firefox上运行此Js获得的数据是从头至尾内存都不会超过70M。这已经说明IE一直都没有解决这种Js内存泄露的问题,即便我用的版本已是最新的IE8.0。

能够想象在现在Ajax运用愈来愈多,用户体验要求愈来愈高的状况下,网页的体积会愈来愈庞大,可能很频繁的Js程序员须要作的事情就是在某个DOM元素例如Div里添加不少Html代码,用innerHTML赋值进去,而后用户触发某事件后又整个替换掉innerHTML,那么被替换之前的Html代码极可能带有这样的环状结构,致使页面只要不刷新,内存就会一直泄露着愈来愈严重,直到吃光机器内存。

因此咱们提倡人为的打破这种环状结构, 即在DOM元素被抛弃以前移除绑定在上面的Js Event Handler,移除的方法就涉及到DOM事件模型的讨论范围了,我已在另一篇讨论文章中详细机讲解W3C标准的DOM事件模型和IE的到底有什么区别了,有兴趣的能够看一看。

固然浏览器厂商特别是IE也但愿能负起必定的责任起来,早日大一统,算是为广大Js程序员造福吧!
相关文章
相关标签/搜索