js 溢出

这些关于js溢出的质料来自 csdn上,并非自己所写。(附件中有完整的测试程序)

 

1.

 

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

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

我们来看一个经典的例子说明问题——

JScript code
 
  
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> ( 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 );



这个例子的意义是创建出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的到底有什么区别了,有兴趣的可以看一看。


2.

 

运行后确实是这样,火狐内存没得啥子显著变化,IE内存直速攀升--!
LZ的代码有点问题哈loop()},修改了下:

JScript code
 
  
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> window.onload = function () { ( function (limit, delay){ var queue = new Array( 5 ); var n = 0 ; 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 ' ; }; return s; } function process(n){ queue.push(makeSpan(n)); var s = queue.shift(); // 数组的shift()方法是在数组装满元素才起效,即返回的是元素对象,否则返回undefined if (s) s.parentNode.removeChild(s); } function loop(){ if (n < limit){ process(n); n += 1 ; setTimeout(loop,delay); } } loop(); })( 10000 , 5 ); };

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值