21

我一直在读同样的东西:

“直接在 DOM 元素上存储属性值是有风险的,因为可能存在内存泄漏。”

但是有人可以更详细地解释这些风险吗?

4

2 回答 2

16

(按属性,我假设您指的是 DOM 元素的属性。)

DOM 元素上的自定义属性是否安全?

一些浏览器在销毁时没有很好地清理 DOM 元素。因此保留了对其他元素、相同元素或大型数据集的引用,从而导致泄漏。我相信这在较新的浏览器中很大程度上得到了解决。

无论如何,在一个元素上存储少量数据是无害的,并且非常方便,因此请谨慎对待该警告。


使用 jQuery 是.data()一个安全的选择吗?

不是特别。使用 jQuery 的自定义数据存储存储数据有其自身的内存泄漏的可能性,不幸的是它们不仅仅影响旧的浏览器。

为了避免泄漏,您需要绝对确定.data()在销毁元素时清洁元素。当您使用 jQuery 销毁元素时,这是自动的,但如果您不这样做,您将有影响每个浏览器的内存泄漏。


有哪些可能导致泄漏的示例?

假设有一堆.data()链接到#foo元素。如果我们使用 jQuery 方法删除元素,我们是安全的:

$("#foo").remove(); // associated .data() will be cleaned automatically

但是如果我们这样做,我们就会有一个跨浏览器兼容的泄漏:

var foo = document.getElementById("foo");
foo.parentNode.removeChild(foo);

或者,如果#foo是某个其他元素的后代,其内容在没有 jQuery 的情况下被清除,这将是同样的问题。

otherElement.innerHTML = "";

在这两种情况下,都没有使用 jQuery 来删除#foo,因此它.data()与元素永久解除关联,并且我们的应用程序存在泄漏。


因此,如果我从不直接使用 DOM API,我是否安全?

你更安全,但另一种可能发生的方式是如果我们加载多个 DOM 操作库。考虑到 jQuery 使用以下代码帮助我们做到这一点:

var $jq = jQuery.noConflict();

现在我们可以允许$引用prototypejsor了mootools,jQuery 被引用了$jq

问题是那些其他库不会清理 jQuery 设置的数据,因为他们不知道。

因此,如果 jQuery 上有一些数据#foo,并且mootools用于销毁该元素,我们就会有内存泄漏。


如果我从不使用.data()jQuery 怎么办?这能让我安全吗?

可悲的是没有。jQuery 使用相同的.data()机制来存储其他数据,例如事件处理程序。因此,即使您从未调用将.data()某些自定义数据与元素相关联,您仍然可能会因上述示例而导致内存泄漏。

大多数时候您可能不会注意到泄漏,但根据代码的性质,它们最终会变得大到足以成为问题。

于 2012-10-09T15:18:08.873 回答
12

根据jQuery 文档

在 Internet Explorer 9 之前的版本中,如果不删除属性(使用 .removeProp( )) 在从文档中删除 DOM 元素之前。要安全地在 DOM 对象上设置值而不发生内存泄漏,请使用 .data()。

于 2012-10-09T15:17:51.033 回答