欢迎光临杨雨的个人博客站!

杨雨个人网站-杨雨个人博客-杨照佳

杨雨个人博客网站

关注互联网和搜索引擎的个人博客网站

首页 > WEB开发 > JavaScript >

闭包会造成内存走漏吗?

发布时间:2016-11-23  编辑:杨雨个人博客网站   点击:   

 媒介

  在谈内存走漏这个题目之前先看看JavaScript的垃圾网络机制,JavaScript 具有自动垃圾网络机制,就是找出那些不再继承行使的变量,然后开释其占用的内存。为此,垃圾网络器会凭证牢靠的时距离断(或代码执行中预定的网络时刻)。常用的的要领有两种,即标志清晰和引用计数。

闭包会造成内存泄露吗?

  标志破除

  JavaScript 中最常用的垃圾网络方法是标志破除(mark-and-sweep)。垃圾网络器在运行的时辰会给存储在内存中的全部变量都加上标志(可以行使任何标志方法)。然后,它会去掉情形中的变量以及被情形中的变量引用的变量的标志。而在此之后再被加上标志的变量将被视为筹备删除的变量,缘故起因是情形中的变量已经无法会见到这些变量了。最后,垃圾网络器完成内存破除事变,烧毁那些带标志的值并接纳它们所占用的内存空间。

  引用计数

  引用计数(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 元素变乱处理赏罚措施的闭包,而这个闭包则又建设了一个轮回引用(变乱将在第13 章接头)。因为匿名函数生涯了一个对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://itbyc.com/web/javascript/13043.html
转载请注明出处。
分享是一种快乐,也是一种美德:
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
博客首页 | WEB开发 | 网站运营 | CMS使用教程 滇ICP备14002061号-1