闭包是一个非常强大的特性,但人们对其也有诸多无解。一种危言耸听的说法是闭包会造成内存泄露。

局部变量本来应该在函数退出的时候被解除引用,但如果局部变量被封闭在闭包形成的环境中,那么这个局部变量就能一直生存下去。从这个意义上看,闭包的确会使一些数据无法被及时销毁。使用闭包的一部分原因是我们选择主动把一些变量封存在闭包中,因为可能在以后还需要使用这些变量,把这些变量放在闭包中和放在全局作用域,对内存方面的影响是一致的,这里并不能说成是内存泄露。如果在将来需要回收这些变量,我们可以手动把这些变量设为null。

跟闭包和内存泄露有关系的地方是,使用闭包的同时比较容易形成循环引用,如果闭包的作用域链中保存着一些DOM节点,这时候就有可能造成内存泄露。但这本身并非闭包的问题,也并非JavaScript的问题。在IE浏览器中,由于BOM和DOM中的对象是使用C++以COM对象的方式实现的,而COM对象的垃圾收集机制采用的是引用计数策略。在基于引用计数策略的垃圾回收机制中,如果两个对象之间形成了循环引用,那么这两个对象都无法被回收,但循环引用造成的内存泄露在本质上也不是闭包造成的。

Javascript 的垃圾回收机制,我现在知道的有两种:标记、计数。

标记清除:主流策略,并且与此问题无关。

引用计数:容易在循环引用时出现问题的策略。因为计数记录的是被引用的次数,所以循环引用时计数并不会消除。导致无法释放内存。IE 9 - 的问题是在环境中bom和dom不是原生的js对象,而是com对象,而com对象的垃圾收集机制是引用计数策略。换句话说,只要ie中存在着com对象,就会存在循环引用的问题。比如

var element=document.getElementById("someElement");
var myobject=new Object();
myobject.element=element;
element.someObject=myobject;

这个例子中js对象和dom对象之间建立了循环引用,由于存在这个循环引用,即使将com对象从页面移除,也永远不会被回收。为避免类似问题,应该在不使用它们的时候手动把js对象和com对象断开。

myobject.element=null;
element.someObject=null;

 
ie9之前的浏览器对javascript对象和com对象使用不用的垃圾收集机制,因此闭包在ie的这些版本中会导致一些特殊的问题
比如

function assignHandler(){
var element=document.getElementById("someElement");
element.onclick=function(){
alert(element.Id);
}
}

以上代码创建了一个作为element元素事件处理程序的闭包,这个闭包又创建了一个循环引用,由于匿名函数保存了一个对assignHandler()的活动对象的引用,因此就会导致无法减少element的引用数,因此,只要匿名函数存在,element的引用至少是1,因此所占的内存就无法回收,要改下才能解决

function assignHandler(){
var element=document.getElementById("someElement");
var id=element.Id;

element.onclick=function(){
alert(id);
};
element=null;
}

通过把element.Id的副本保存在本地的一个变量中,并且在闭包中引用改变量消除循环引用,但仅仅做到这一步,还不能消除内存泄漏,因为闭包会引用包含函数的整个活动对象,而其中包含着element;即使不直接引用,包含函数的活动对象中仍然保存着一个引用,因此有必要把element变量设置为null。

 
同样,如果要解决循环引用带来的内存泄露问题,我们只需要把循环引用中的变量设为null即可。将变量设置为null意味着切断变量与它此前引用的值之间的联系。当垃圾收集器下次运行时,就会删除这些值并回收他们占用的内存。

关于js闭包是否真的会造成内存泄漏(转载)的更多相关文章

  1. 深入理解Node.js中的垃圾回收和内存泄漏的捕获

    深入理解Node.js中的垃圾回收和内存泄漏的捕获 文章来自:http://wwsun.github.io/posts/understanding-nodejs-gc.html Jan 5, 2016 ...

  2. js 垃圾回收机制和引起内存泄漏的操作

    垃圾回收机制 JS中最常见的垃圾回收方式是标记清除. 工作原理:是当变量进入环境时,将这个变量标记为“进入环境”.当变量离开环境时,则将其标记为“离开环境”.标记“离开环境”的就回收内存. 工作流程: ...

  3. 【JS档案揭秘】第一集 内存泄漏与垃圾回收

    程序的运行需要内存,对于一些需要持续运行很久的程序,尤其是服务器进程,如果不及时释放掉不再需要的内存,就会导致内存堆中的占用持续走高,最终可能导致程序崩溃. 不再需要使用的内存,却一直占用着空间,得不 ...

  4. Java 理论与实践: 用弱引用堵住内存泄漏---转载

    要让垃圾收集(GC)回收程序不再使用的对象,对象的逻辑 生命周期(应用程序使用它的时间)和对该对象拥有的引用的实际 生命周期必须是相同的.在大多数时候,好的软件工程技术保证这是自动实现的,不用我们对对 ...

  5. JS基础-垃圾回收机制与内存泄漏的优化

    [V8引擎]浅析Chrome V8引擎中的垃圾回收机制和内存泄露优化策略 垃圾回收机制 如何判断回收内容 如何确定哪些内存需要回收,哪些内存不需要回收,这是垃圾回收期需要解决的最基本问题.我们可以这样 ...

  6. 转《js闭包与内存泄漏》

    首先,能导致内存泄漏的一定是引用类型的变量,比如函数和其他自定义对象.而值类型的变量是不存在内存泄漏的,比如字符串.数字.布尔值等.因为值类型是靠复制来传递的,而引用类型是靠类似c语言中的指针来传递的 ...

  7. js晋级篇——前端内存泄漏探讨

    1.IE7/8 DOM对象或者ActiveX对象循环引用导致内存泄漏 循环引用分为两种: 第一种:多个对象循环引用 var a=new Object; var b=new Object; a.r=b; ...

  8. Android内存泄漏检测利器:LeakCanary

    Android内存泄漏检测利器:LeakCanary MAR 28TH, 2016 是什么? 一言以蔽之:LeakCanary是一个傻瓜化并且可视化的内存泄露分析工具 为什么需要LeakCanary? ...

  9. [Android]Android内存泄漏你所要知道的一切(翻译)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/7235616.html Android内存泄漏你所要知道的一切 ...

随机推荐

  1. Android ActionBar详解(二)--->使用ActionBar显示选项菜单

    MainActivity如下: package cc.testsimpleactionbar1; import android.os.Bundle; import android.app.Activi ...

  2. ExpandableListView 箭头样式

    ExpandableListVivew是ListView的子类,它在普通ListView的基础上进行了扩展,它把应用中的列表项分为几组,每组里 又可包含多个列表项.ExpandableListVive ...

  3. Android 开发之Matrix图片处理类的使用

    在Android中,对图片的处理需要使用到Matrix类,Matrix是一个3 x 3的矩阵,他对图片的处理分为四个基本类型: 1.Translate————平移变换 2.Scale————缩放变换 ...

  4. Linux下查看内核、CPU、内存及各组件版本的命令和方法

    Linux下查看内核.CPU.内存及各组件版本的命令和方法 Linux查看内核版本: uname -a                        more /etc/*release       ...

  5. VS2008发布程序

    下列附有VS2008发布程序介绍:vc2008程序发布指南2008-05-03 17:46vc2008开发的程序的发布方式可以有5种方式: 1. 采用静态链接到crt和MFC. 只要你拥有组成程序的所 ...

  6. Paths on a Grid(规律)

    Paths on a Grid Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 23270   Accepted: 5735 ...

  7. 发送请求工具—Advanced REST Client

    Advanced REST Client是Chrome浏览器下的一个插件,通过它能够发送http.https.WebSocket请求.在Chrome商店下搜索Advanced REST Client, ...

  8. pv ticketlock解决虚拟环境下的spinlock问题

    最近看邮件,有注意到pv ticketlock相关的消息,貌似jeremy 几年前的东东,终于将要被收录到linux 3.12里面. 先说下pv ticketlock这东西,http://blog.x ...

  9. MyGui 3.2.0(OpenGL平台)的编译

    MyGui是一个用来创建用户图形界面的库,用于游戏和3D应用程序.这个库的主要目标是达到:快速.灵活.易用. 1.下载准备: 源代码:http://svn.code.sf.net/p/my-gui/c ...

  10. android UI进阶之用【转】

    android UI进阶之用ViewPager实现欢迎引导页面 摘要: ViewPager需要android-support-v4.jar这个包的支持,来自google提供的一个附加包.大家搜下即可. ...