Javascript 为什么将数据存储为元素的属性有风险?

Javascript 为什么将数据存储为元素的属性有风险?,javascript,jquery,Javascript,Jquery,我一直在读同样的东西: “直接在DOM元素上存储属性值有风险,因为可能存在内存泄漏。” 但有人能更详细地解释这些风险吗?根据: 在9版之前的Internet Explorer中,使用.prop()设置DOM 元素属性设置为除简单基元值以外的任何值 (数字、字符串或布尔值)如果属性为 在删除DOM元素之前未删除(使用.removeProp()) 从文件中删除。在没有内存的DOM对象上安全地设置值 泄漏,请使用.data() (根据属性,我假设您指的是DOM元素的属性。) DOM元素上的自定义属性安

我一直在读同样的东西:

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

但有人能更详细地解释这些风险吗?

根据:

在9版之前的Internet Explorer中,使用.prop()设置DOM 元素属性设置为除简单基元值以外的任何值 (数字、字符串或布尔值)如果属性为 在删除DOM元素之前未删除(使用.removeProp()) 从文件中删除。在没有内存的DOM对象上安全地设置值 泄漏,请使用.data()

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

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();
现在我们可以允许
$
引用
prototypejs
mootools
,jQuery由
$jq
引用

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

因此,如果jQuery有一些关于
#foo
的数据,并且
mootools
被用来销毁该元素,那么我们就有了内存泄漏


如果我从未在jQuery中使用
.data()
,该怎么办?这样我就安全了吗?

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


大多数情况下,您可能没有注意到漏洞,但根据代码的性质,它们最终可能会变得足够大,成为一个问题。

您在哪里读到过这篇文章???我的想法正好相反。内存泄漏最常见的问题通常是循环引用。阅读我在@tybro0103上的评论;不要相信你在网上看到的一切。在
data-
属性中存储数据不会导致内存本身泄漏。话虽如此,我还是对下面@Werner的答案投了赞成票,因为他引用了一个有信誉的来源。请引用你的来源。@ZZZBOV:我认为来源是上一个问题。你能解释一下你说的“销毁元素时使用jQuery清理元素的.data()是什么意思吗”@Anne:是的。与元素关联的所有数据、处理程序等都存储在名为
jQuery.cache
的单个数据存储中。元素与其存储中的数据之间的链接是一个序列号,jQuery直接将该序列号放在元素上。如果使用jQuery销毁元素,jQuery将在存储中查找数据,并将其删除。问题在于,如果不使用jQuery销毁元素,那么序列号将随元素一起丢失,
jQuery.cache
中的关联数据将永久孤立。在我看来,这比在元素上存储一点数据要严重得多;.prop是其他的吗?我发现下面链接上的公认答案很好地解释了.attr()和.prop()之间的区别: