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

Jos*_*eph 10 javascript jquery circular-reference

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

它是如何打破参考圈的?

$(div1).data('item', div2);
$(div2).data('item', div1);
Run Code Online (Sandbox Code Playgroud)

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

jfr*_*d00 13

当您将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()数据都可能泄漏,并且可能泄漏的任何已删除的DOM对象.data()都会泄漏.但是,如果您只使用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);
Run Code Online (Sandbox Code Playgroud)

因为您使用普通Javascript删除了DOM元素,所以jQuery没有机会清理以前存储的数据.DOM元素本身将被垃圾收集,但.data()您之前存储的值现在在jQuery的存储中是孤立的,并且本质上是一个"泄漏",因为它可能永远不会被清除.另一方面,如果你这样做:

$(elem).data("someKey", "someValue");
$(elem).remove();
Run Code Online (Sandbox Code Playgroud)

然后,jQuery将看到您正在删除DOM元素,并且还将清除您存储的数据.data().

查看它如何工作的一种相当简单的方法是使用非最小化版本的jQuery创建一个行脚本,然后$(elem).data("key", "whatever")在调试器中单步调用并观察它是如何工作的.