浏览器中的内存泄露(续)解决方案
作者:winter 来源:winter博客 发布时间:2008-05-03 17:14:00
阅读上一篇:浏览器中的内存泄露
4.内存泄露的解决方案
显式类型转换
首先说说最容易处理的情况 对于类型转换造成的错误,我们可以通过显式类型转换来避免:
var s=newString("lalalalala");//此处将string转换成object
alert(s.length);
这个太容易了,算不上正经方案。不过类型转换泄露也就这一种处理方法了。
避免事件导致的循环引用
在比较成熟的js程序员里,把事件函数写成闭包是再正常不过了:
function A(){
var a=document.createElement("div");
a.onclick=function(){
alert("hi");
}
}
这将导致内存泄露。按照IBM那两位老大的说法,当然是把函数放外面或者a=null就没问题了,不过还要访问A()里面的变量呢?假如有下面的代码:
function A(){
var a=document.createElement("div");
var b=document.createElement("div");
a.onclick=function(){
alert(b.outerHTML);
}
return a;
}
如何将它的逻辑表达出来 还避免内存泄露? 分析一下这个内存泄露的形式:只要onclick的外部环境中不包含a那么,就不会泄露。那么办法有2个一是将环境到a的引用断开 另一个是将function到环境的引用断开,但是,如果要在函数中访问b就不能将Function放到外面,如果要返回a的值,就不能a=null,怎么办呢?
解决方案1:
构造一个不含a的新环境
function A(){
var a=document.createElement("div");
var b=document.createElement("div");
a.onclick=BuildEvent(b);
return a;
}
function BuildEvent(b)
{
return function(){
alert(b.outerHTML);
}
}
a本身可以通过this访问,将其它需要访问的外层函数变量传递给BuildEvent就可以了。保持BuildEvent定义和调用的参数名一致,会带来方便。
解决方案2:
在return 之后a=null,不可能? 看看下面:
function A(){
try{
var a=document.createElement("div");
var b=document.createElement("div");
a.onclick= function(){
alert(b.outerHTML);
}
return a;
} finally {
a=null;
}
}
finally在try之后执行,如果finall块不返回值,才会返回try块的返回值。
延迟appendChild
还记得函数的lazy initalize吧,对于ie恶心至极的DOM操作泄露,我们需要用类似的方法去处理。在一个函数中构造一个复杂对象,在需要的时候将之appendChild到DOM树上,这是很常见的做法,但在IE6中,这样做将导致所谓的"插入顺序内存泄露",没有别的办法,我们只能用一个数组parts保存子节点,编写一个appendTo方法先序遍历节点树,去把它挂在某个DOM节点上。
function appendTo(Element)
...{
Element.appendChild(this);
if(!this.parts)return;
for(var i=0;i<this.parts.length;i++)
parts.appendTo(this);
}
垃圾箱
对于ie7,我比较无可奈何,因为DOM对象不会被CG程序回收,只有离开页面时会被回收,所以我的建议是:使用DOM要有节制,尽量多用innerHTML吧...... good luck.
一旦你使用了DOM对象,千万不要试图o=null,你可以设置一个叫做Garbage的div并且将其display设置为none,将不用的DOM对象存入其中(就是appendChild上去)就好了
代理对象
这是Ext的做法,这里只是顺带提一下。将每个元素用一个"代理对象"操作,不论appendChild还是其他操作都不是对DOM对象本身的操作,而是通过这个代理对象操作。这是一个很不错的Proxy模式,不过要想避免泄露还是需要一点功夫的,并非用了Proxy之后就不会泄露,有时反而更容易泄露。
5 .FAQ
内存泄露是内存占用很大么? 不是,即使1byte内存也叫做内存泄露。
程序中提示,内存不足,是内存泄露么?不是,这一般是无限递归函数调用导致栈内存溢出。
内存泄露是哪个区域泄露?堆区,栈区是不会泄露的。
window对象是DOM对象么?不是,window对象参与的循环引用不会内存泄露。
内存泄露后果是什么?大多数时候后果不很严重,但过多DOM操作会导致网页执行变慢。
跳转页面后,内存泄露仍然存在么?仍然存在,直到关闭浏览器。
FireFox也会内存泄露么?FF2仍然有内存泄露
猜你喜欢
- 如何发送一个XMLHttpRequest的检索的特定部分HTML标题数据。<html> <head> <tit
- 也许你刚刚来到一家公司,他们希望进行一些“可用性”工作。你可能是一名UI设计师,业务分析师,或前端开发人员,一名产品经理,或者负责用户体验部
- 要防止同一用户同时登陆,首页应该记录在线用户的信息(这里与用户名为例),然后判断正在登陆的用户里面是否已存在。在这里使用一个cache存放已
- xhtml+css页面制作过程中问题的解决方案,说是解决方案应该有点过了,充其量只不过是给刚刚开始学标准页面制作的朋友们的一些小建议,如果讲
- 又有人说设session.timeout=99999。这种同样不行,session有最大时间限制。我经过测试发现最大值为24小时,也就是说你
- http://swik.net/Ajax/Ajax+Mistakes在某网站瞎逛时,发现这个链接,进去逛了逛,觉得很有意思,大家也可以去看看
- 尽管有很多规范URL的标准,例如RFC 3987,但实际应用中却非常混乱。本文主要介绍浏览器发送URL到服务器的一些特性,作为开发和应用的参
- 数据库文件在使用过程中,日志文件会越来越大。小则几个G,大的可能几十上百G都有可能,有时实在是没有必要为它浪费太大的硬盘存储空间。所以可以把
- 如何做一个文本书写器?我们有下面的的函数,可做“文本书写器”:<%function WriteToFile(FileName
- 你不得不承认,今天网络发展之迅速,信息流动速度之快、量之大,是我们不曾考虑过的,但现在它就真真切切地摆在我们面前。如何接纳信息,怎么处理、消
- 提高SQL执行效率的几点建议:◆尽量不要在where中包含子查询;关于时间的查询,尽量不要写成:where to_char(dif_date
- 一个封装好的JavaScript拖动类,使用方便:<div id="idDrag" style="bor
- 首先是最常规的方法:<p id="para" title="cssrain demo!" on
- 一个asp显示当前日期农历的代码函数,效果 今天是:农历丁亥年(猪)八月十三。调用方便!Function nl()'获取当前系统时间
- 可以使用 Application 对象在给定的应用程序的所有用户之间共享信息。基于 ASP 的应用程序同所有的 .asp 文件一样在一个虚拟
- write2vin 的 PPT原文路宛兮写的简介:本文解释了以下问题: 1.什么是用户体验? 2.谁发明了这个术语?他想表达什么意思? 3.
- 联合结果集 新建临时工数据表 代码如下:CREATE TABLE T_TempEmployee (FIdCardNumber VARCHAR
- asp网站程序在国内运用很广,但是类似于im286.asp?id=20050307213811这样的url有点不利于搜索引擎的收录,也就是说
- 1.查询表名: 代码如下:select table_name,tablespace_name,temporary from user_tab
- 近期公司准备开发一个计费项目,数据库当然还是选用我最信赖的Oracle了。由于一部分基础数据在一台Win2000 Server的S