jQuery data()如何打破循环引用

10

我已经阅读了关于为什么它更好如何实现它的内容。但我不太明白它是如何打破循环引用的?

它是如何打破引用循环的?

$(div1).data('item', div2);
$(div2).data('item', div1);

比如说,上面的div互相指向,怎样避免这种情况?我有个想法,但我想确认一下我的想法是否正确。

1个回答

15
在某些浏览器中,当你将一个DOM对象的引用作为属性放在该DOM对象上时,就会出现循环引用问题。这样,你就有两个互相指向的DOM对象。删除一个具有自定义属性的DOM对象并不会清除该自定义属性。如果垃圾收集器不够聪明,则无法意识到该DOM引用不计入其中,因此它会被卡住,这可能会导致内存泄漏。
`.data()` 解决了这个问题,因为 `.data()` 数据不在 DOM 对象上。它只是一个 JavaScript 数据结构,可以通过唯一的字符串 ID 与 DOM 对象关联起来。
其中一个令人困惑的部分是,当您使用 ` .data("key")` 读取时,如果 JavaScript 的 `.data()` 数据结构中没有找到 `key`,那么只有 jQuery 才会查找名为 `"data-key"` 的 DOM 对象上的属性。但是,每当你使用 ` .data("key", "myData")` 写入数据时,它永远不会写入 DOM 对象,而只是写入 JavaScript 数据结构。
因此,由于 `.data()` 永远不会将数据写入 DOM 对象,因此就不可能存在浏览器难以处理的这些类型的循环引用。
还有一些关于 `.data()` 数据结构有用的知识点。当使用 jQuery 的 ` .remove()` 从 DOM 中删除元素或调用 `$(elem).html("new html")` 时,jQuery会清除任何已删除项上的 `.data()` 数据。这是一个情况下,最好不要将 jQuery 与纯JavaScript混合使用。如果您正在使用 ` .data()`,那么应始终使用 jQuery 函数从 DOM 中删除项目,以便适当地清除 `.data()`。否则,这样可能会导致内存泄漏(`.data()` 数据和在 `.data()` 中引用的任何已删除DOM对象都可能会泄漏)。但是,如果只使用 jQuery 方法从 DOM 中删除项目(包括替换 innerHTML),则 jQuery 将适当地清理事物,并且不会出现泄漏。
例如,这将创建一个内存泄漏:
// suppose elem is a DOM element reference

// store some data in jQuery's data storage on behalf of a DOM element
$(elem).data("someKey", "someValue");

// remove DOM element with plain Javascript
elem.parentNode.removeChild(elem);
因为你使用纯Javascript删除了DOM元素,所以jQuery没有机会清除之前存储的数据。DOM元素本身将被垃圾回收,但你之前存储的.data()值现在被孤立在jQuery的存储中,实际上是一个“泄漏”,因为它很可能永远不会被清除。另一方面,如果你这样做:
$(elem).data("someKey", "someValue");
$(elem).remove();

然后,jQuery会发现您正在删除DOM元素,并且还会清除使用.data()存储的数据。

了解它的工作原理的一个相当简单的方法是,使用非最小化版本的jQuery创建一个几行脚本,然后在调试器中逐步调用$(elem).data("key", "whatever"),并观察其工作方式。


请你能否用一个例子来阐述第5段的解释? - techloris_109
@techloris_109 - 已添加示例。 - jfriend00
有人知道我可以用.data()存储多少以MB或KB为单位的数据吗? - EaBengaluru
1
@EaBengaluru - 唯一的限制是本地浏览器/JavaScript环境中可用的内存量。网页通常使用MB级别的图像,因此在该范围内可能是可以接受的。 - jfriend00
@jfriend00 非常感谢您的快速回复!!!我明白了。 - EaBengaluru

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接