3

I often read it's bad practice, because it's hard to maintain, but doing:

document.getElementsByTagName("h1")[0].foo = {"key":"value"};

compared to using the recommended jQuery alterantive:

$.data($(document.getElementsByTagName("h1")[0]), "foo", {"key":"value"});

is just so much faster: jsperf

Both data and my hack are not visible in a debugger like Firebug, so from a "visibility" point of view there is no difference in using either one.

Question:
Why is bad practice to store information directly on the element?

13
  • If neither is visisible you haven't looked closely enough. Commented Nov 14, 2013 at 10:48
  • wouldn't $('h1').eq(0).data('foo', {"key":"value"}) be a better idea ? Commented Nov 14, 2013 at 10:49
  • 1
    The advantage of using data() is that it gets populated if you use the data-* attributes in your HTML Commented Nov 14, 2013 at 10:52
  • 1
    @frequent - setting a property directly is much faster, no suprise there, but setting it with data() is safe and avoids circular references and DOM errors, and that's mostly why it's slower. Commented Nov 14, 2013 at 10:52
  • 1
    @RohanKumar - Doesn't really matter, jQuery creates an object called $.cache, and each element that has data() attached only gets a property with an ID, this ID is then used as a key in the $.cache object to look up whatever data is stored, so the data is never stored on the element itself, it's in a seperate object thus avoiding memory leaks and circular references etc. To work with HTML5 data attributes, .data() always checks getAttribute('data-') first to see if any data is attached directly to the element in the markup. Commented Nov 14, 2013 at 10:58

2 Answers 2

5

There are a couple reason why custom properties such as .foo are not advisable:

  1. In some browsers, depending upon what you assign to the custom properties, you can end up with circular references between DOM and JS which can lead to memory leaks in some circumstances.

  2. The element property namespace is reserved for use by the browser and for future properties. That's why the HTML5 spec even suggests that all custom attributes be prefixed with the data- prefix to put them all in that one name. So, if you start randomly adding properties to your DOM elements, you are likely to conflict with something now or in the future.

jQuery's .data() creates a javscript object and stores all the data elements created with .data() in javascript. It used one custom properties as an index into the .data() world so that it can find the right items that belong to a particular DOM element. It has no chance of a DOM <--> JS circular reference and your keys used with .data() will never conflict with DOM property names.


FYI, the more common way to use .data() is via method on a jQuery object such as:

$("h1").eq(0).data("foo", {"key":"value"})

It is not uncommon that native methods are faster than jQuery alternatives because jQuery does more in order to offer its extended feature set and cross browser compatibility, though jQuery is generally for it's speed to not be noticed. You would generally use jQuery to help with cross browser compatibility and to use it's features to speed up your development effort. Performance optimizations are generally done much later only when you've isolated and profiled a particular performance issue and there are times when some jQuery can be replaced with native code to speed up a particular operation.

Sign up to request clarification or add additional context in comments.

Comments

1

If it is for the single element then an id selector would be best, I think.

You can use :first selector like,

$.data($("h1:first"), "foo", {"key":"value"});

And using an data-* attribute you can set multiple attributes in one single data rather than using multiple-attributes (which may not works in some browsers).

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.