我已阅读why it's better和how it's implemented。但我真正理解的是 它如何打破循环引用? 。
它如何打破参考圈?
$(div1).data('item', div2);
$(div2).data('item', div1);
例如,上面的div指向对方,它是如何被阻止的?我有预感,但我只是想确定我的预感是否正确。
答案 0 :(得分:13)
当您将DOM对象上的DOM对象的引用作为该DOM对象上的属性时,在某些浏览器中会出现循环引用问题。然后,您有两个相互指向的DOM对象。删除带有自定义属性的DOM对象并不清除该自定义属性。一个不聪明的垃圾收集器并没有意识到这个DOM引用不会被计数,所以它会被卡住,并且有几种方法可能导致泄漏。
.data()
解决了这个问题,因为.data()
数据不在DOM对象上。它只是一个javascript数据结构,可以通过唯一的字符串ID与DOM对象相关联。
令人困惑的部分是,当您使用.data("key")
阅读并且key
未在javascript .data()
数据结构中找到时,那么只有这样,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")
并观察它是如何工作的。< / p>