javascript - 从内存中的 HTML 元素取消绑定(bind)内联 javascript 事件

标签 javascript jquery html memory-leaks

如何从 HTML 元素中完全解除内联 javascript 事件的绑定(bind)?

我试过:

  • 取消委托(delegate) body 元素的事件
  • 解除事件与元素的绑定(bind)
  • 甚至从 HTML 元素中删除事件属性

至少令我惊讶的是,仅删除 onchange 属性 (.removeAttr('onchange')) 就能够阻止事件再次触发。

<input type="text" onchange="validateString(this)"></input>

我知道这对代表来说是可能的,而且这可能是最好的方式,但请继续努力。这个例子纯属假设,只是为了提出问题。


所以假设情况是这样的:

我正在编写一个 javascript 验证库,它通过内联 HTML 属性将 javascript 事件绑定(bind)到输入字段,如下所示:

<input type="text" onchange="validateString(this)"></input>

但是,我想通过取消绑定(bind)我的事件来让这个库变得更好一些,这样在单页应用程序中使用这个库的人就不必管理我的事件处理程序,这样他们就不必必须通过将输入事件连接到我假设的验证库中的函数来弄乱他们的代码……无论如何。这些都不是真的,但它似乎是一个不错的用例。

这是 Hypothetical Validation Library.js 的“示例”代码:

http://jsfiddle.net/CoryDanielson/jwTTf/


要进行测试,只需在文本框中键入内容,然后单击其他位置即可触发更改事件。在打开 Web 检查器并在“时间轴”选项卡上进行记录的情况下执行此操作。突出显示与触发更改事件(多次触发更改事件)相关的时间线区域,您将看到每个更改事件的事件监听器(在下面的窗口中)增加 100。如果管理和删除得当,每个事件监听器都会在呈现新输入之前被正确删除,但我还没有找到使用内联 javascript 事件正确执行此操作的方法。

这段代码的作用是这样的:

  1. onChange,输入元素触发验证函数
  2. 该函数验证输入并在成功时为边框着色
  3. 然后 1 秒后(为了演示内存泄漏)输入元素连续 100 次被相同的 HTML 替换,而没有取消绑定(bind) change 事件(因为我不知道该怎么做......这就是问题在这里)。这模拟了在单页应用程序中更改 View 。这会在 DOM 中创建 100 个新的 eventListener,这可以通过 Web 检查器看到。

    • 有趣的笔记。 $('input').removeAttr('onchange'); 实际上会阻止将来触发 onchange 事件,但不会对 eventListener/DOM 进行垃圾回收在网络检查器中可见的东西。

此屏幕截图是更改事件触发 3 次后的截图。每次都会用相同的 HTML 呈现 100 个新的 DOM 节点,我试图在替换 HTML 之前从每个节点解除绑定(bind) onchange 事件。

enter image description here


更新:我回到这个问题并使用 JSFiddle 做了一个快速的小测试以确保答案有效。我运行了数十次“测试”,然后等待 - 果然,GC 通过并处理了业务。

enter image description here

最佳答案

我认为您没有什么可担心的。虽然内存不能再被引用并且最终会被垃圾回收,但它仍然会显示在 Web Inspector 内存窗口中。当 GC 决定对其进行垃圾回收时(例如,当浏览器内存不足或在某个固定时间后),内存将被垃圾回收。细节由 GC 实现者决定。您可以通过单击 Web Insepctor 窗口底部的“收集垃圾”按钮来验证这一点。我运行的是 Chrome 23,在你的验证框中输入文本大约 5 或 6 次后,内存使用率崩溃了,显然是由于垃圾收集。

这种现象并非内联事件所特有。我看到了一个类似的模式,只是重复分配一个大数组,然后覆盖对该大数组的引用,为 GC 留下大量孤立内存。内存会增加一段时间,然后 GC 启动并完成它的工作。

关于javascript - 从内存中的 HTML 元素取消绑定(bind)内联 javascript 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14784867/

相关文章:

Javascript:通过引用传递对象

javascript - 使用 mongoose 查询嵌套文档

javascript - 更新 couchdb 文档日期格式

javascript - 如果验证码不安全,可以使用什么代替?

jquery - 谷歌地图关闭信息框

Javascript 函数工厂嵌套在 jQuery 就绪函数中嵌套的立即函数中

javascript - 转到列表中的 eq 项

html - 在 AngularJs 中淡入和淡出?

javascript - 在表格单元格内循环对象并创建无序列表

javascript - 尝试从不同邮政编码获取推文时出现问题