使用此/ self引用的javascript闭包会导致内存泄漏吗?

时间:2012-02-17 00:18:53

标签: javascript events memory-leaks this

根据我对内存泄漏的理解,在闭包内引用超出范围的var会导致内存泄漏。

但是,创建“that”var也是一种常见做法,以保留“this”引用并在闭包中使用它,尤其是对于事件。

那么,做这样的事情有什么用呢:

SomeObject.prototype.createImage = function(){
    var that = this,
        someImage = new Image();
    someImage.src = 'someImage.png';
    someImage.onload = function(){
        that.callbackImage(this);
    }
};

这不会给项目增加一点泄漏吗?

3 个答案:

答案 0 :(得分:4)

是的,是的,它确实会导致内存泄漏,至少在某些浏览器中是这样(猜猜哪个)。这是让您信任各种可用框架之一的更有说服力的理由之一,并通过其机制设置所有事件处理程序,而不是直接添加“DOM 0”事件处理程序。

Internet Explorer(至少在9之前,可能包括9)在内部有两个内存分配机制(至少):一个用于DOM,一个用于JavaScript(井JScript)。他们彼此不了解。因此,即使释放了DOM节点,也不会释放示例中的任何闭包内存。

编辑 - 哦,我提到框架的原因是它们通常包含试图缓解此问题的代码。避免将任何内容附加到DOM节点属性是最安全的方法之一。例如,值得担心的所有浏览器(包括古老的IE版本)都有将事件处理程序附加到DOM节点的替代方法。

答案 1 :(得分:1)

IE有一段时间,涉及DOM元素的循环引用(通常在将函数分配给侦听器时由闭包形成)导致内存泄漏,例如

function foo() {
  var someEl = document.getElementById('...');
  someEl.onclick = function() {...};
}

但是,我认为它们已得到修复或修补,除非测试另有说明,否则可以忽略它们。还有很多方法可以避免这种闭包,因此即使它们是一个问题,也可以解决它们(例如,不要创建涉及DOM元素的循环引用)。

修改

使用库或任何其他附加侦听器的方法仍然可以创建循环引用和内存泄漏,例如在IE中:

function foo() {
  var el = document.getElementById('d0');

  // Create circular reference through closure to el
  el.attachEvent('onclick', function(){bar(el);});

}

function bar(o) {
  alert(o == window.event.srcElement);  // true
}

window.onload = foo;

以上使用 attachEvent 添加一个监听器(几乎所有框架将用于IE< 9,包括jQuery)但仍然创建一个涉及a的循环引用在某些IE版本中,DOM元素会泄漏。因此,只使用库无法解决问题,您需要了解原因并避免它们。

答案 2 :(得分:1)

在黑暗中拍摄,但我认为:

someImage.onload = function(){
    that.callbackImage(this);
    someImage.onload = null
}

会清除that

留下的“内存泄漏”