I\'m developing code using jQuery and need to store data associated with certain DOM elements. There are a bunch of other questions about how to store arbitrary data w
Let me rephrase the question: What are the practical differences between the two data binding options available?
Actually there are three options:
$(e).prop('myKey', myValue);
$(e).data('myKey', myValue);
$(e).attr('data-myKey', myValue);
Note: OP’s e.myKey = myValue
is practically the same as the .prop()
line.
.prop()
, i.e. expando properties.attr('data-*')
.data()
→ read the last two paragraphsIf you ever want to pass the data around with serialized HTML you need the .attr()
solution. I.e. whenever you use things like .innerHTML
or .html()
or want to construct snippets from strings with data included. The same applies if you want to use CSS selectors like elem[data-myKey]
. Disadvantage: you can only store strings.
If you don’t need your data to be visible in the DOM or available to CSS interaction .data()
and .prop()
might work. Their biggest advantage is: they can hold any Javascript value.
.prop()
biggest disadvantage is the possibility of name collision. Only pick names you can be sure will not be used as native property ever. E.g. scope
as key is a bad idea, because it exists on some HTML elements...
Now comes .data()
. The other answers seem to swear on it, I avoid it. The memory leaks related to .prop()
and expando properties in general belong to the past, so that is no advantage any more. But you will be secured against name collisions with HTML properties. That is an advantage. But you get a bunch of disadvantages:
$(e).data('myKey')
draws its uninitialized value from the data-myKey
attribute if available, runs JSON.parse() on those and sometimes returns that or falls back to the string value of the attribute. Once you set $(e).data('myKey', myValue)
you lose the relationship with the data-myKey
attribute, which nevertheless lives on with its “old” value, shown in DOM and in CSS interactions. On top, the key name you use is subject to possible name mangling. I.e. if you ever decide to read all key-value via $(e).data()
the keys in that object might be different.
Because of this erratic behavior (mixing expando property technology with data-*
attributes) and inconsistent get/set design I always avoid .data()
.—Fortunately that is easy to do with .prop()
and .attr()
(with data-*
keys for compliance).
If you really want to use .data()
to avoid name clashes with native properties, my advice: do not mix with data-*
attributes, consider them a different thing, and avoid name clashes with those.—Does that make sense? For automatic clash avoidance you have to avoid clashes elsewhere manually. Great design.