I keep reading the same thing:
\"Storing property values directly on DOM elements is risky because of possible memory leaks.\"
But c
(By attribute, I assume you are referring to properties on DOM elements.)
Are custom properties on DOM elements safe?
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.
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?
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.
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.
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:
$("#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.
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.
So if I never use the DOM API directly, I'm safe?
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:
var $jq = jQuery.noConflict();
Now we can allow $
to refer to prototypejs
or mootools
, and jQuery is referenced by $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.
So if jQuery has some data on #foo
, and mootools
is used to destroy that element, we have our memory leak.
What if I never use .data()
in jQuery? Does that make me safe?
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.
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.
According to the jQuery documentation:
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().