Javascript中的事件处理程序、闭包和垃圾收集

Javascript中的事件处理程序、闭包和垃圾收集,javascript,jquery,events,garbage-collection,Javascript,Jquery,Events,Garbage Collection,我还没有在我的应用程序中遇到内存泄漏,但我担心将来可能出现的问题。我想知道,如果这样做: SomeClass.prototype.someMethod= function() { var that= this this.$div2.click(function() { that.someMethod2(); }); } 假设这个.$div2被附加到另一个div这个.$div1。如果我打电话 this.$div1.remove(); 然后丢失我的Some

我还没有在我的应用程序中遇到内存泄漏,但我担心将来可能出现的问题。我想知道,如果这样做:

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

我之所以这样做,是因为this.$div2中的事件处理程序可能会保留对HTML元素this.$div2的引用,并且由于变量“that”的缘故,还会通过闭包保留对SomeClass实例的引用

那么,我是否应该关心像这样正确地删除所有事件和HTML元素?或者简单地删除“根”元素(这个$div1)就可以解决问题

this.$div2
附加到
this.$div1
。如果我调用
this.$div1.remove()
然后丢失对我的
SomeClass
实例的引用
SomeClass
实例是否被垃圾回收

是的,当对它的所有引用都丢失时(也包括通过事件处理程序的引用),实例可以被垃圾回收

那么HTML元素this.$div2呢
this.$div2
不会在DOM中,因为它被附加到
this.$div1

它当前是否附加到DOM并不重要。如果某些不可收集的对象引用了
$div1
,它还可以访问其子节点
$div2
以及该对象的事件处理程序,因此从处理程序引用的实例将不可收集

我之所以这样做,是因为
this.$div2
中的事件处理程序可能会保留对HTML元素
this.$div2
的引用,并且由于变量“that”,它还会通过闭包保留对
SomeClass
实例的引用

这是一个循环引用,引擎应该能够很好地处理它(当没有从外部引用循环内的任何对象时,它可以被收集)。但是,当一个DOM对象涉及到这个循环时,(旧的?)Internet Explorer无法做到这一点

由于这个原因,()在内部调用,它分离所有事件侦听器

那么,我是否应该关心像这样正确地删除所有事件和HTML元素?或者简单地删除“根”元素(这个$div1)就可以解决问题

是的,在jQuery包装器上调用
remove
会自动删除所有事件(来自所有子元素)和DOM节点

我是否应该关心如何正确删除所有事件和HTML元素 像这样

简而言之,答案是否定的!至少在99%的情况下,这并不重要,因为一个DOM元素使用的内存与一个网页使用的总内存相比微不足道

然而,释放处理不需要的对象所使用的内存始终是一个好的实践,但是您不能说GC肯定会释放元素所使用的内存,因为垃圾收集完全由浏览器决定!理论上,GC应该只在没有对DOM元素的引用时启动,至少是这样,但是在像JavaScript这样的语言中,你没有明确地告诉你对对象的运行时间,JavaScript中的事情很快就会变得混乱:一个函数可能会将对象传递给更多的函数,对象可能会保存为另一个对象中的成员,对象可能会通过闭包等被引用,因此完全取决于浏览器如何收集以及收集什么

在您的例子中,删除
div1
会释放html文档,元素不会在视图中呈现,事实上jQuery的
remove
方法负责删除所有事件、expando属性以及附加到元素的子元素以及元素本身,但是,您在另一个对象中保留了对
div1
div2
的引用,使这两个DOM元素都成为孤立元素!删除
SomeClass
实例变量将释放对DOM元素的所有引用,使其成为垃圾收集的候选对象,但下面是一个棘手的
变量,该变量导致DOM元素通过clusure引用
SomeClass
!该问题在IE中称为
循环参考

存储对一个对象的引用的JavaScript对象和DOM元素 另一个原因是Internet Explorer的垃圾收集器无法回收垃圾 内存,导致内存泄漏


这个特定的漏洞主要是历史感兴趣的,即如果您将动态创建元素,然后将事件分配给它们。我认为你的代码不是一个好方法。你应该这样做:

对于需要事件的固定元素,请使用这两个函数;第一个在构造函数中调用,第二个在析构函数中调用

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

对于动态对象。在创建元素时添加事件,并在销毁元素之前删除这些事件。

我认为应该这样做。垃圾收集器应该跟踪引用,因此理论上,当最后一个引用消失时,该项应该是垃圾收集的候选项。我想知道JS引擎中的那些是否也可以分析无法访问的代码,并标记仍然有引用但其引用未使用的项……这取决于。对于一个经典的webapp,这并不是一个真正的问题,因为您经常提交到服务器,服务器加载或刷新不同的视图。随着单页应用的出现,这可能会成为一个问题,尤其是像IE这样的“死气沉沉”浏览器。@asgoth我正在制作单页应用。一个必须在不刷新页面的情况下可靠运行至少12小时的变量,因此我担心垃圾收集
on_Events: function() {
   $('your_form').on('event_name', {element_Selector}, callback_function)
},
off_Events: function() {
   $('your_form').off('event_name', {element_Selector}, callback_function)
}