我读过 why it's better和 how it's implemented .但我不太明白的是它如何打破循环引用?。
它是如何打破引用圈的?
$(div1).data('item', div2);
$(div2).data('item', div1);
比如上面的div相互指向,如何防止?我有预感,但我只是想确定我的预感是否正确。
最佳答案
当您将对 DOM 对象的引用作为该 DOM 对象的属性放置在 DOM 对象上时,某些浏览器会发生循环引用问题。然后,您有两个相互指向的 DOM 对象。删除带有自定义属性的 DOM 对象并不会清除该自定义属性。一个不那么聪明的垃圾收集器没有意识到这个 DOM 引用没有计数,所以它被卡住了,并且有几种方法可以导致泄漏。
.data()
解决了这个问题,因为 .data()
数据不在 DOM 对象上。它只是一个 javascript 数据结构,可以通过唯一的字符串 ID 与 DOM 对象相关联。
其中一个令人困惑的部分是,当您使用 .data("key")
读取时,key
未在 javascript 中找到。 data()
数据结构,然后并且只有到那时,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")
在调试器中观察它是如何工作的。
关于javascript - jQuery data() 如何打破循环引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10004593/