闭包会造成内存泄漏吗?

人工智能2025-11-05 16:03:424162

前言

在谈内存泄漏这个问题之前先看看JavaScript的闭包垃圾收集机制,JavaScript 具有自动垃圾收集机制,成内存泄就是闭包找出那些不再继续使用的变量,然后释放其占用的成内存泄内存。为此,闭包垃圾收集器会按照固定的成内存泄时间间隔(或代码执行中预定的收集时间)。常用的闭包的方法有两种,即标记清楚和引用计数。成内存泄

1. 标记清除

JavaScript 中最常用的闭包垃圾收集方式是标记清除(mark-and-sweep)。垃圾收集器在运行的成内存泄时候会给存储在内存中的所有变量都加上标记(可以使用任何标记方式)。然后,闭包它会去掉环境中的成内存泄变量以及被环境中的变量引用的变量的标记。而在此之后再被加上标记的闭包变量将被视为准备删除的变量,原因是成内存泄环境中的变量已经无法访问到这些变量了。IT技术网***,闭包垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。

2. 引用计数

引用计数(reference counting)的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次数加1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减1。当这个值的引用次数变成0 时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。这样,当垃圾收集器下次再运行时,它就会释放那些引用次数为零的值所占用的内存。

Netscape Navigator 3.0 是最早使用引用计数策略的源码库浏览器,但很快它就遇到了一个严重的问题,请看下面这个例子:

function problem(){     var objectA = new Object();     var objectB = new Object();     objectA.someOtherObject = objectB;     objectB.anotherObject = objectA; }  

说明:objectA 和objectB 通过各自的属性相互引用,即这两个对象的引用次数都是2,在采用标记清除策略的实现中,由于函数执行之后,这两个对象都离开了作用域,因此这种相互引用不是个问题。但在采用引用计数策略的实现中,当函数执行完毕后,objectA 和objectB 还说明将继续存在,因为它们的引用次数永远不会是0。假如这个函数被重复多次调用,就会导致大量内存得不到回收。

为此,Netscape 在Navigator 4.0 中放弃了引用计数方式,然而引用计数导致的麻烦并未就此了结。IE9以前中有一部分对象并不是原生JavaScript 对象。例如,其BOM 和DOM 中的对象就是使用C++以COM(Component Object Model,云服务器提供商组件对象模型)对象的形式实现的,而COM 对象的垃圾收集机制采用的就是引用计数策略。因此,即使IE 的JavaScript 引擎是使用标记清除策略来实现的,但JavaScript 访问的COM 对象依然是基于引用计数策略的。换句话说,只要在IE 中涉及COM 对象,就会存在循环引用的问题。

比如:

var element = document.getElementById("some_element"); var myObject = new Object(); myObject.element = element; element.someObject = myObject;  

DOM 元素(element)与一个原生JavaScript 对象(myObject)之间创建了循环引用。其中,变量myObject 有一个名为element 的属性指向element 对象;而变量element 也有一个属性名叫someObject 回指myObject。由于存在这个循环引用,即使将例子中的DOM 从页面中移除,它也永远不会被回收。

解决办法:将变量设为null从而切断变量与它此前引用的值之间的连接。

myObject.element = null; element.someObject = null;  

看完上面的内容,我来谈正题。

闭包不会引起内存泄漏

由于IE9 之前的版本对JScript 对象和COM 对象使用不同的垃圾收集。因此闭包在IE 的这些版本中会导致一些特殊的问题。具体来说,如果闭包的作用域链中保存着一个HTML 元素,那么就意味着该元素将无法被销毁请看例子:

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

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

解决办法前言已经提到过,把element.id 的一个副本保存在一个变量中,从而消除闭包中该变量的循环引用同时将element变量设为null。

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

总结:闭包并不会引起内存泄漏,只是由于IE9之前的版本对JScript对象和COM对象使用不同的垃圾收集,从而导致内存无法进行回收,这是IE的问题,所以闭包和内存泄漏没半毛钱关系。

这篇文章里做了详细的测试,有兴趣的可以点击查看

本文地址:http://www.bzve.cn/html/355c65798987.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

全站热门

我想很多人都试过装双系统,windows系统在重装的时候总是把MBR重写了,重装windows后无法找到ubuntu的引导。恢复引导其实也很简单,找个ubuntu的安装盘,从安装盘启动,试用ubuntu,打开终端。 1、运行命令:sudo fdisk -l (这里不是数字1,是字母l),找到ubuntu所在根目录。2、运行命令:sudo mkdir /media/tmpdir 建立临时文件夹,然后输入命令:sudo mount /dev/sda11 /media/tmpdir挂载系统。3、接下来是最重要的一步,输入命令: sudo grub-install --root-directory=/media/tmpdir /dev/sda (注意,这里就是sda,后面不要写成sda11),假如显示no error report,则表示基本成功了。 4、接下来,重启系统.这时引导已经像往常一样了。但先不要进入windows,先进入ubuntu,在终端中输入命令:sudo update-grub2 更新grub后方成功完成,这时候就可以重启进入任意一个系统了注意事项:可能你显示的跟我不一样,因为我这是在真正的ubuntu系统下截的图,我这里的挂载情况是这样的。

纳尼?自建K8s集群日志收集还能通过JMQ保存到JES

域名的商业价值是什么?域名存在着怎样的商业价值?

全局视角看技术-Java多线程演进史

Ubuntu 8.04 ( Hardy Heron ) 是完全支持 Compiz Fusion所有特性的一个版本.但是主要的问题是没办法来配置这些特性.为了配置这些不同的选项,我们需要使用一个叫 Compiz Config的工具软件.打开新立得管理器,搜索 Compiz Config 然后安装就可以了.一旦安装好了 Compiz Config ,运行他,你会看到一个类似于如下图所示的界面:这个界面非常的简单,选中了的选项表示这个效果是启用的,没有选中的选项表示这个效果是没有启用的.为了配置单个的效果例如键绑定点击图片的效果.现在我就来演示一下一些我最喜欢的特效和实际的效果图.1)屏幕上火焰效果:你可以使用这个特效在你的屏幕上画火字,为了使用这个效果,你需要使用组合键shift+win键,并点击鼠标左键,火焰就会被喷在屏幕上.当火焰文字在你的屏幕上,在你的正常的桌面上工作区的时候,你依然可以做所有的事情,例如浏览网页,假如想清除火焰文字,请按组合键shift+win+c键,这个时候火焰文字就会被清除.2)展览特效:这个效果能让你预览的桌面.使用这个特效只需要按组合键win+e 3)摆动窗口:一个非常受众多Compiz Fusion玩家喜爱的特效,他主要是使你的窗口像水一样摆动.4)水滴效果:使你的桌面像下雨一样的非常好,非常迷人的一个效果.通过使用ctrl+win键来激活这个效果.  5)窗口切换:使用一种类似ITunes的cover flow的方式来切换窗口。通过使用win+tab键来使用这个种效果 6)窗口圆环切换:使你的窗口形成一个圆环,并使用简单的alt+tab来切换窗口.因为这个插件禁止了alt+tab的默认的浏览的功能 现在,让我们开始随心所欲的定制自己喜欢的 Compiz fusion 特效吧!

全局视角看技术-Java多线程演进史

cm域名怎么样?如何注册cm域名?

Python-master,实用Python脚本合集!

友情链接

滇ICP备2023006006号-39