为什么将数据存储为元素的属性存在风险?

时间:2021-04-04 20:39:11

I keep reading the same thing:

我继续阅读同样的事情:

"Storing property values directly on DOM elements is risky because of possible memory leaks."

“直接在DOM元素上存储属性值是有风险的,因为可能存在内存泄漏。”

But can someone explain these risks in more detail?

但有人可以更详细地解释这些风险吗?

2 个解决方案

#1


16  

(By attribute, I assume you are referring to properties on DOM elements.)

(根据属性,我假设您指的是DOM元素的属性。)

Are custom properties on DOM elements safe?

DOM元素的自定义属性是否安全?

Some browsers have not cleaned up DOM elements very well when destroyed. References to other elements, the same element, or large sets of data were therefore retained, causing leaks. I believe this is largely resolved in newer browsers.

有些浏览器在销毁时没有很好地清理DOM元素。因此保留了对其他元素,相同元素或大量数据的引用,从而导致泄漏。我相信这在较新的浏览器中已基本解决。

In any case, storing small amounts of data on an element is innocuous, and can be very convenient, so take that warning with a grain of salt.

在任何情况下,在元素上存储少量数据都是无害的,并且可以非常方便,因此请用一粒盐警告。


Is using jQuery's .data() a safe alternative?

使用jQuery的.data()是一种安全的替代方案吗?

Not especially. Storing data using jQuery's custom data store has its own potential for memory leaks, and unfortunately they don't merely affect old browsers.

不是特别。使用jQuery的自定义数据存储来存储数据有其自身的内存泄漏潜力,不幸的是它们不仅仅影响旧的浏览器。

In order to avoid leaks, you'd need to be absolutely certain you clean an element's .data() when destroying an element. This is automatic when you use jQuery to destroy the element, but if you don't, you'll have memory leaks that affect every browser.

为了避免泄漏,您需要绝对确定在销毁元素时清理元素的.data()。当您使用jQuery来销毁元素时,这是自动的,但如果不这样做,您将会遇到影响每个浏览器的内存泄漏。


What are some examples that can cause leaks?

有哪些例子可能导致泄漏?

Let's say that there's a bunch of .data() linked to the #foo element. If we use jQuery methods to remove the element, we're safe:

假设有一堆.data()链接到#foo元素。如果我们使用jQuery方法删除元素,我们是安全的:

$("#foo").remove(); // associated .data() will be cleaned automatically

But if we do this, we have a cross-browser compatible leak:

但是如果我们这样做,我们就会遇到跨浏览器兼容的漏洞:

var foo = document.getElementById("foo");
foo.parentNode.removeChild(foo);

Or if #foo is a descendant of some other element whose content is being cleared without jQuery, it would be the same issue.

或者如果#foo是其他元素的后代,其内容在没有jQuery的情况下被清除,那么问题也是如此。

otherElement.innerHTML = "";

In both cases, jQuery was not used to remove #foo, so its .data() is permanently disassociated from the element, and our application has a leak.

在这两种情况下,jQuery都不用于删除#foo,因此它的.data()永久地与元素无关,并且我们的应用程序有泄漏。


So if I never use the DOM API directly, I'm safe?

所以,如果我从不直接使用DOM API,我会安全吗?

You're safer, but another way this can happen is if we load more than one DOM manipulation library. Consider that jQuery helps us do this with the following code:

你更安全,但另一种方法是,如果我们加载多个DOM操作库。考虑到jQuery帮助我们使用以下代码执行此操作:

var $jq = jQuery.noConflict();

Now we can allow $ to refer to prototypejs or mootools, and jQuery is referenced by $jq.

现在我们可以允许$引用prototypejs或mootools,jQuery由$ jq引用。

The trouble is that those other libraries will not clean up data that was set by jQuery, because they don't know about it.

麻烦的是那些其他库不会清理jQuery设置的数据,因为他们不知道它。

So if jQuery has some data on #foo, and mootools is used to destroy that element, we have our memory leak.

因此,如果jQuery在#foo上有一些数据,并且mootools用于销毁该元素,那么我们就会发生内存泄漏。


What if I never use .data() in jQuery? Does that make me safe?

如果我从不在jQuery中使用.data()怎么办?这会让我安全吗?

Sadly, no. jQuery uses the same .data() mechanism to store other data, like event handlers. Therefore even if you never make a call to .data() to associate some custom data with an element, you can still have memory leaks caused by the examples above.

可悲的是没有。 jQuery使用相同的.data()机制来存储其他数据,比如事件处理程序。因此,即使您从未调用.data()将某些自定义数据与元素相关联,您仍然可能会因上述示例而导致内存泄漏。

Most of the time you may not notice the leaks, but depending on the nature of the code, they can eventually grow large enough to be a problem.

大多数情况下,您可能没有注意到泄漏,但根据代码的性质,它们最终会变得足够大而成为一个问题。

#2


12  

According to the jQuery documentation:

根据jQuery文档:

In Internet Explorer prior to version 9, using .prop() to set a DOM element property to anything other than a simple primitive value (number, string, or boolean) can cause memory leaks if the property is not removed (using .removeProp()) before the DOM element is removed from the document. To safely set values on DOM objects without memory leaks, use .data().

在版本9之前的Internet Explorer中,使用.prop()将DOM元素属性设置为除简单原始值(数字,字符串或布尔值)之外的任何内容都可能导致内存泄漏(如果未删除该属性)(使用.removeProp( ))从文档中删除DOM元素之前。要在没有内存泄漏的情况下安全地设置DOM对象的值,请使用.data()。

#1


16  

(By attribute, I assume you are referring to properties on DOM elements.)

(根据属性,我假设您指的是DOM元素的属性。)

Are custom properties on DOM elements safe?

DOM元素的自定义属性是否安全?

Some browsers have not cleaned up DOM elements very well when destroyed. References to other elements, the same element, or large sets of data were therefore retained, causing leaks. I believe this is largely resolved in newer browsers.

有些浏览器在销毁时没有很好地清理DOM元素。因此保留了对其他元素,相同元素或大量数据的引用,从而导致泄漏。我相信这在较新的浏览器中已基本解决。

In any case, storing small amounts of data on an element is innocuous, and can be very convenient, so take that warning with a grain of salt.

在任何情况下,在元素上存储少量数据都是无害的,并且可以非常方便,因此请用一粒盐警告。


Is using jQuery's .data() a safe alternative?

使用jQuery的.data()是一种安全的替代方案吗?

Not especially. Storing data using jQuery's custom data store has its own potential for memory leaks, and unfortunately they don't merely affect old browsers.

不是特别。使用jQuery的自定义数据存储来存储数据有其自身的内存泄漏潜力,不幸的是它们不仅仅影响旧的浏览器。

In order to avoid leaks, you'd need to be absolutely certain you clean an element's .data() when destroying an element. This is automatic when you use jQuery to destroy the element, but if you don't, you'll have memory leaks that affect every browser.

为了避免泄漏,您需要绝对确定在销毁元素时清理元素的.data()。当您使用jQuery来销毁元素时,这是自动的,但如果不这样做,您将会遇到影响每个浏览器的内存泄漏。


What are some examples that can cause leaks?

有哪些例子可能导致泄漏?

Let's say that there's a bunch of .data() linked to the #foo element. If we use jQuery methods to remove the element, we're safe:

假设有一堆.data()链接到#foo元素。如果我们使用jQuery方法删除元素,我们是安全的:

$("#foo").remove(); // associated .data() will be cleaned automatically

But if we do this, we have a cross-browser compatible leak:

但是如果我们这样做,我们就会遇到跨浏览器兼容的漏洞:

var foo = document.getElementById("foo");
foo.parentNode.removeChild(foo);

Or if #foo is a descendant of some other element whose content is being cleared without jQuery, it would be the same issue.

或者如果#foo是其他元素的后代,其内容在没有jQuery的情况下被清除,那么问题也是如此。

otherElement.innerHTML = "";

In both cases, jQuery was not used to remove #foo, so its .data() is permanently disassociated from the element, and our application has a leak.

在这两种情况下,jQuery都不用于删除#foo,因此它的.data()永久地与元素无关,并且我们的应用程序有泄漏。


So if I never use the DOM API directly, I'm safe?

所以,如果我从不直接使用DOM API,我会安全吗?

You're safer, but another way this can happen is if we load more than one DOM manipulation library. Consider that jQuery helps us do this with the following code:

你更安全,但另一种方法是,如果我们加载多个DOM操作库。考虑到jQuery帮助我们使用以下代码执行此操作:

var $jq = jQuery.noConflict();

Now we can allow $ to refer to prototypejs or mootools, and jQuery is referenced by $jq.

现在我们可以允许$引用prototypejs或mootools,jQuery由$ jq引用。

The trouble is that those other libraries will not clean up data that was set by jQuery, because they don't know about it.

麻烦的是那些其他库不会清理jQuery设置的数据,因为他们不知道它。

So if jQuery has some data on #foo, and mootools is used to destroy that element, we have our memory leak.

因此,如果jQuery在#foo上有一些数据,并且mootools用于销毁该元素,那么我们就会发生内存泄漏。


What if I never use .data() in jQuery? Does that make me safe?

如果我从不在jQuery中使用.data()怎么办?这会让我安全吗?

Sadly, no. jQuery uses the same .data() mechanism to store other data, like event handlers. Therefore even if you never make a call to .data() to associate some custom data with an element, you can still have memory leaks caused by the examples above.

可悲的是没有。 jQuery使用相同的.data()机制来存储其他数据,比如事件处理程序。因此,即使您从未调用.data()将某些自定义数据与元素相关联,您仍然可能会因上述示例而导致内存泄漏。

Most of the time you may not notice the leaks, but depending on the nature of the code, they can eventually grow large enough to be a problem.

大多数情况下,您可能没有注意到泄漏,但根据代码的性质,它们最终会变得足够大而成为一个问题。

#2


12  

According to the jQuery documentation:

根据jQuery文档:

In Internet Explorer prior to version 9, using .prop() to set a DOM element property to anything other than a simple primitive value (number, string, or boolean) can cause memory leaks if the property is not removed (using .removeProp()) before the DOM element is removed from the document. To safely set values on DOM objects without memory leaks, use .data().

在版本9之前的Internet Explorer中,使用.prop()将DOM元素属性设置为除简单原始值(数字,字符串或布尔值)之外的任何内容都可能导致内存泄漏(如果未删除该属性)(使用.removeProp( ))从文档中删除DOM元素之前。要在没有内存泄漏的情况下安全地设置DOM对象的值,请使用.data()。