javascript垃圾回收和IE内存泄露

   昨天跟同事讨论问题时提起了内存泄露,想到了以前考scjp时碰到的垃圾回收的题目,觉得挺有意思,就去查了一些有关javascript垃圾回收的资料,贴出来跟大家分享一下。


   垃圾回收,简单的说就是收回某些无用对象所占用的内存以供重新使用,垃圾回收机制通常有一个优先级较低的线程来维护。在java里采用有向树的方式管理内存,那些从根节点出发不可达(unreachable)的对象即被认为是垃圾回收的目标,这种方式有效避免了循环引用的问题。而COM组件(DOM)和Javascript的垃圾回收机制都是基于引用计数(犀牛书上说javascript1.1是基于引用计数的,1.2应该也是),而且在IE里,Dom对象和Javascript对象的垃圾回收又是相互分离的,所以如果这两种对象出现了循环调用就会导致垃圾回收失效,内存泄露,这是IE内存泄露最常见的一种方式。

    一个循环引用导致内存泄露的例子:(原例见后面的参考文章:微软关于IE内存泄露的分析和解决方案)

 

     因为例子里对象很少,所以容易看出来,但是我们一般遇到的页面里,特别是使用prototype和jquery这些框架时,$等操作会大量的绑定dom对象到js对象,调用中的相互引用几乎是难以避免的。所以循环引用才被大家认为是Web页面中最常见和最主要的泄漏方式。

     还有一种内存泄露方式是闭包(Closure)。闭包本身是一种编程机制,函数式编程就需要用到它,而且在一些情景下闭包会很有用。

   比如一个做加法的工厂方法:

   AdderFactory方法内部那个匿名方法在它返回以后仍然能够记住y的值,以供以后使用,但是在这个匿名方法调用之后y已经不存在了,我们称这个匿名方法叫闭包。(呵呵,可能我理解的有问题,具体的见后面的参考文章:What are closures? )

 

 一个闭包导致内存泄露的例子:

      闭包又是js事件处理机制很容易涉及的问题,为了避免因此而导致IE内存泄露,prototype,jquery这些js框架也提供了相应的解决办法,比如解除事件绑定的方法:stopObserveing()和unbind(),同时对页面的unload事件也做了处理。我们从jquery源码中也可以看出来作者为防止内存泄露的一些处理,prototype没看,应该也有类似的语句:

 // Prevent memory leaks in IE

 // And prevent errors on refresh with events like mouseover in other browsers

// Window isn't included so as not to unbind existing unload events

jQuery(window).bind("unload", function() {
    jQuery("*").add(document).unbind();
    jQuery("*").add(document).unbind();
});

      还有其他一些内存泄露的方式,后面的参考文章里有相关的介绍。这些内存泄露应该跟页面是否跳转到其他页面,是否reload没有什么关系,应用程序域是服务器端的概念,我觉得应该跟客户端的内存泄露也没有直接关系。对象不可达,不可访问,只能说明我们无法访问它,或者说只是我们程序员知道它应该被垃圾收集,而事实是dom和javascript采用的是两种分离的垃圾收集机制,前面的循环调用等都有可能导致垃圾收集失败,本该被gc的对象依然占用着内存(可以试一下参考文章JScript Memory Leaks中的例子)。所以,我觉得将不用的js变量设为null来告诉javascript的gc重用这些内存,以及取消事件绑定还是很有必要的,至少在那些用js大量操作dom对象的页面里应该尽量做到这些

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值