内存泄露之我见

一、 产生内存泄露的原因

  在内存管理方面,JavaScript采用的是自动垃圾回收机制。简单地说,当我们在JavaScript中创建一个对象时,脚本引擎会负责将内存分配给对象,当引擎发现当前堆栈中没有对该对象的引用时,就会将该对象进行垃圾回收(即销毁)。我们可以通过将一个对象的引用置为空(null),显式的将一个对象销毁并回收。

和其他高级语言一样,JavaScript本身提供的这套垃圾回收机制本身并没有任何问题,在通常情况下,这套机制十分奏效。但是当我们将JavaScript与HTML DOM、XML DOM或者其他COM组件混合编写程序时(而在AJAX开发中通常如此),就会发生意想不到的内存泄漏问题。

     Internet Explorer采用的是一种引用计数系统。在这套系统中,每一个HTML元素或者对象都具有一个引用计数,它记录了当前有多少个对象正在引用该元素,当计数为零的时候,它就会被自动销毁。这种引用计数系统在早期的Web应用开发看来似乎十分奏效,但是其实该方案本身就存在了一些盲点,而正是这些缺憾最终导致了著名的JavaScript内存泄漏,

二、 内存泄露的几种解决方式

 1、使用平台提供的$attachEvent方法订购事件

HTML DOM提供了一套订购、退订事件的机制,是分别通过attachEvent和detachEvent这一对方法实现的,但是往往我们只订购事件,而忘了detachEvent,这也是容易引发循环引用的潜在隐患之一。

MWFrameowrk框架在底层扩展了$attachEvent全局方法,它会在窗体重新加载或关闭前将之前订购过的事件进行批量退订。该方法原型如下:

 $attachEvent(element, eventName, handler);

该方法包含3个参数,其中,element参数为需要订购事件的DOM元素,eventName为事件名称,而handler则为事件处理函数。

例如:平台提供的FlowPanel.js中第114行代码:

   me.internalTitle.attachEvent("ondragstart", function()

     {

            return false;

     });

可以修改为:

$attachEvent(me.internalTitle, "ondragstart", function()

{

      return false;

  }); 

2、减少匿名函数的使用

   查询一下匿名函数的信息【】】】】】】

例如:平台提供的PerformanceCounterClass.js第18行代码:

window.attachEvent("onload", function()

            {

                        document.body.appendChild(_iframe);

                        window.setTimeout(me.report, 1000);

            });

可以将匿名函数独立出一个有名字的函数,修改后的代码如下:

$attachEvent(window,"onload",appendIframe);

function appendIframe()

                        {

                                    document.body.appendChild(_iframe);

                                    window.setTimeout(me.report, 1000);

                        }

3 避免使用循环引用

   当两个对象互相进行引用的时候,就产生了循环引用。例如下面的代码:

<script>

      var myGlobalObject;

      function SetupLeak()//产生循环引用,因此会造成内存泄露

      {

            myGlobalObject= document.getElementById("LeakedDiv");//

            document.getElementById("LeakedDiv").expandoProperty = myGlobalObject;

      }

</script>

<body onload="SetupLeak()">

      <div id="LeakedDiv"></div>

</body>

我们可以看到,myGlobalObject指向了一个DOM对象,而这个DOM对象的一个属性又指向了myGlobalObject,循环引用出现,造成了内存泄露。

解决方案很简单,在确保属性不被使用后,加入如下代码就可以了。

function BreakLeak()//解开循环引用,解决内存泄露的问题

{

            document.getElementById("LeakedDiv").expandoProperty = null;

}

以上这种循环引用是比较简单的一种,但是,当我们程序非常复杂的时候,发现和修改就没有那么容易了。

   在技改大修模块中,为了方便用户使用,在项目名称上加入了超链接,用于打开项目的详细信息页面。代码如下:

dataGrid_new.columns["XMMC"].renderCell = function(dataCell, container)

    {

             dataCell.dataGrid = dataGrid_new;

             _renderXMCXMMCCell_DX(dataCell, container);

    };

  这段代码存在着严重的内存泄露,而且随着数据列表中的数据条数增多,内存泄露会越来越严重。解决起来就比较复杂,为了最大程度的减少对代码的修改。干脆将该功能取消掉,用点击放大镜的方式来打开项目的详情信息页面。

4 页面退出时将全局变量置为null】】

   在页面退出的时候,使用onDisposing事件,将全局变量置为null.
5 Interval】

将代码

window.setInterval(me.report, 15 * 1000);

修改为:

     var _iTimerInterval;

            _iTimerInterval = window.setInterval(me.report, 15 * 1000);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值