事件处理程序,关闭和在Javascript垃圾回收(Event handlers, closures

2019-08-04 02:31发布

我没有运行到我的应用程序内存泄漏,但我很担心在未来可能出现的问题。 我想知道,如果做这样的事情:

SomeClass.prototype.someMethod= function() {
    var that= this
    this.$div2.click(function() {
        that.someMethod2();
    });
}

并让说这个。$ DIV2追加到另一个DIV这一点。$ DIV1。 如果我打电话

this.$div1.remove();

后来失去我SomeClass的实例的引用并在SomeClass的实例被垃圾回收? 至于中的HTML元素。$ DIV2? 这一点。$ DIV2不会是DOM中,因为它被附加到这一点。$ DIV1。

我问这个,因为在此。$ DIV2事件处理程序可能会保持到HTML元素这一点。$ DIV2参考,并保持到SomeClass的实例的引用,通过关闭,因为变量“那个”的。

所以我应该关心适当地去除这样的所有事件和HTML元素? 或者干脆删除“根”元素(这一点。$ DIV1)解决了这个问题?

Answer 1:

this.$div2附加到this.$div1 。 如果我把this.$div1.remove(); 后来又失去了我的参考SomeClass实例时的SomeClass实例被垃圾回收?

是的,当所有对它的引用都将丢失 - 还有那些通过事件处理 - 实例可以得到垃圾收集。

并且怎么样的HTML元素this.$div2this.$div2不会是DOM中,因为它被附加到this.$div1

不要紧,无论是当前连接到DOM。 如果一些非收藏的对象引用$div1 ,它也可以访问它的子节点$div2与一个人的事件处理程序,所以从处理程序引用的实例不会收藏。

我问这个,因为在事件处理程序this.$div2可能保持到HTML元素的引用this.$div2 ,也保留对实例的引用SomeClass穿过闭合,因为变量“那个”的。

这是一个循环引用, 应由发动机得到很好的处理(当没有圈子里的对象是从外面能得到收集参考)。 然而,(老?)互联网探索者失败时DOM对象参与了一圈做到这一点。

由于这个原因, .remove jQuery的方法 ( 代码 )内部调用(内部) cleanData方法 ,其分离的所有事件侦听器。

所以我应该关心适当地去除这样的所有事件和HTML元素? 或者干脆删除“根”元素(这一点。$ DIV1)解决了这个问题?

是的,要求remove上一个jQuery包装自动删除所有事件(从所有子元素)和DOM节点。



Answer 2:

我应该关心适当地删除这样的所有事件和HTML元素?

最简洁的答案是不! 至少在99%的情况,也不会以任何方式,因为相比于网页使用的全部内存由一个DOM元素使用的内存是小事英寸

然而,它始终是一个很好的做法,以释放不需要的配置对象所使用的内存,但你不能说GC铁定释放该元素使用的内存,因为垃圾收集是完全由浏览器! 从理论上讲GC当有DOM元素的引用应该只踢,至少这是如何Chrome的工作 ,但像JavaScript语言,你不明确的告诉你这个对象在运行时,事情就变得凌乱的JavaScript的如此之快:一个功能可能会传递给更多功能的对象,对象可能会保存远离作为成员另一个对象中,对象可能会通过关闭等引用,所以它完全取决于浏览器如何并收集了什么!

在你的情况下删除div1释放HTML文档和元素在视图不会渲染,其实jQuery的remove ,但是你的方法需要去除附着于该元素的所有事件,expando属性和子元素与元素本身一起照顾,保持一个参考div1div2的又一个目的使得无论DOM元素孤儿元素! 除去SomeClass使他们的候选人进行垃圾回收,但这里的实例变量释放到DOM元素的所有引用了棘手的that变量引起的DOM元素做出的实例的引用SomeClass通过clusure! 这个问题被称为Circular Reference在IE中:

JavaScript对象和DOM引用存储到一个另一个原因Internet Explorer的垃圾收集器不会回收存储元件,从而导致内存泄漏

你可以在这里读更多关于它的内容

这种特殊的泄漏主要是历史兴趣IE <8,但断裂圆形链接的一个很好的例子是避免使用可变that ,而是使用代理或委托给事件处理程序的上下文改变到一些特定的上下文。

ECMA 5绑定方法在谈到DOM事件处理函数退出有用的不断变化的环境,这里是根据你的代码的简单处理程序,而无需使用可变关闭:

this.$div2.click((function() {
        this.someMethod2();
    }).bind(this));


Answer 3:

如果您将动态创建元素,然后分配给他们的活动。 我认为你的代码是不是这样做的好方法。 应按照此方式:

对于固定的元素,如果你需要一个事件,使用这两个函数; 第一个叫的构造,第二次在析构函数。

on_Events: function() {
   $('your_form').on('event_name', {element_Selector}, callback_function)
},
off_Events: function() {
   $('your_form').off('event_name', {element_Selector}, callback_function)
}

对于动态物体。 当创建元素添加事件,只是销毁的元素之前删除这些事件。



文章来源: Event handlers, closures and garbage collection in Javascript