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

我已经阅读了为什么它更好以及它是如何实现的 。 但我真正理解的是如何打破循环引用的呢?

它是如何打破参考圈的?

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

例如,上面的div指向彼此,它是如何被阻止的? 我有预感,但我只是想确定我的预感是否正确。

当您将DOM对象上的DOM对象的引用作为该DOM对象上的属性时,在某些浏览器中会出现循环引用问题。 然后,您有两个相互指向的DOM对象。 删除带有自定义属性的DOM对象不会清除该自定义属性。 不那么聪明的垃圾收集器没有意识到这个DOM引用不计数,因此它会卡住,并且有几种方法可能导致泄漏。

.data()解决了这个问题,因为.data()数据.data() DOM对象上。 它只是一个javascript数据结构,可以通过唯一的字符串ID与DOM对象相关联。

令人困惑的部分是当你用.data("key")读取并且在javascript .data()数据结构中找不到key ,那么jQuery将在DOM上查找属性对象称为"data-key" 。 但无论何时使用.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")并观察它是如何工作的。