【问题标题】:Does a javascript event handler exist in memory even after the DOM element to which it is bound is removed?javascript 事件处理程序是否存在于内存中,即使在它绑定的 DOM 元素被删除后?
【发布时间】:2011-08-18 01:14:40
【问题描述】:

给定以下代码

<div id="app">
  <div id="foo" />
</div>

<script>
  $('#foo').bind('click', function(){});
</script>

我计划替换#app [例如$('#app').html('...');innerHTML = '...';]。我知道我可以使用 jQuery 的 .remove(),它调用一个取消绑定事件的 'destroy' 处理程序。有一个 destroy 处理程序设置来删除事件的事实让我相信,如果不解除绑定事件,当 DOM 元素被删除时,处理程序仍将存在于内存中。

那么,如果 DOM 元素 #foo 不再存在,处理程序是否也会消失,还是会丢失在浏览器内存中?

【问题讨论】:

  • 我也想知道。不太确定,但我想如果 java 发现一个不再被使用的对象,它会在一段时间后清理自己。
  • @robx:JavaScript,不是 Java。是的,JavaScript 是一种垃圾收集语言,但浏览器的 DOM 部分可能不是(几乎可以肯定不是)用 JavaScript 编写的。
  • 哎呀,我一直在思考自己不确定的事情;)

标签: javascript jquery memory-leaks


【解决方案1】:

jQuery 会跟踪事件处理程序本身,这就是为什么你需要使用 unbind (现在是 off 如果你要从 DOM 中删除元素 通过 jQuery 方法(如果您使用 jQuery 的 emptyremove,正如您所提到的,它会在内部自行处理)。这让 jQuery 知道它可以释放它对处理程序的引用。

如果不是这样,那么理论上,您不必做任何事情,因为一旦 DOM 元素从内存中删除,它就不再可访问,因此理论上应该'不要将事件处理程序保存在内存中。这就是理论。现实情况非常不同,很容易导致 DOM 元素 事件处理程序都无法清理的情况(尤其是在 IE 上),因为它们都导致了另一个坚持——内存泄漏。 JavaScript 没有循环引用的问题(它可以理解它们并且可以释放两个相互指向的东西,只要没有 else 指向它们),但是浏览器的 DOM 部分可能会用不同的语言编写,具有不同的垃圾收集机制(IE 使用 COM,它使用引用计数而不是可达性)。 jQuery 可以帮助您避免 IE 的这种陷阱(部分原因是它会跟踪事件处理程序),但您必须使用 unbind(现在 off(或通过 empty 删除元素, remove 等)作为结果。

外卖信息:当你上钩时,你也应该解开。 :-)(和/或在删除元素时使用 jQuery,因为它会处理这个问题。)

有些相关:如果您要添加和删除大量元素,您可能会查看事件委托(jQuery 通过on 的委托签名非常容易)是否有帮助。

【讨论】:

  • 我是这么认为的。我正在将 Backbone.js 用于应用程序,但在源代码中没有看到任何内容,也没有看到有关在 Backbone.View 中设置的解除绑定事件的文档。我见过的许多 Backbone 的在线示例也没有取消绑定任何事件(调用“new View()”会覆盖元素中的内容,但不会对元素的先前子项进行​​任何取消绑定)。如果它们会出现,我想确保我考虑到这些内存泄漏。
【解决方案2】:

刚好阅读了关于 jQuery 的 empty() 方法的文档:

为避免内存泄漏,jQuery 移除 其他结构,如数据和 来自子元素的事件处理程序 在移除元素之前 自己。

【讨论】:

    猜你喜欢
    • 2012-01-22
    • 1970-01-01
    • 2011-02-19
    • 1970-01-01
    • 2014-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多