31

Is it ok to set custom properties on DOM elements, and rely on them persisting?

For example, given

 <html><body><div id="foo"></div></body></html>

Would it be fair to do document.getElementById('foo').bar = "baz";, and expect document.getElementsByTagName('div')[0].bar to equal "baz"?

Note that I'm talking about properties as in normal javascript object properties here, not element attributes.

I'm interested both in how cross-browser it is, and whether its supported in any spec.

Does the DOM API guarantee that the same javascript object will be returned for the same DOM element every time?

10
  • 1
    You can set custom properties, but don't rely on them. They might become standard properties down the road and clash with your code. Better to use the element storage systems that jquery/mootools provide (.data() and the like). Commented Oct 25, 2011 at 20:43
  • 1
    "Does the DOM API guarantee that the same javascript object will be returned for the same DOM element every time?" - I don't understand this question. DOM elements are host objects, not "JavaScript objects" (formally referred to as native objects). Commented Oct 25, 2011 at 20:43
  • 2
    @rampion The node is represented by its Node object. As long as you refer to the same node, you'll get the same object. If you successfully define a new property on a Node object, you should be able to retrieve its value later. Commented Oct 25, 2011 at 21:09
  • 1
    This question is very technical, so you really need to be careful choosing your vocabulary. What exactly is a "DOM element"? And why (when) would it "return" a JavaScript object? What's the difference? And what the hell is a "semantic node"? Commented Oct 25, 2011 at 21:24
  • 1
    possible duplicate of Can I add arbitrary properties to DOM objects? Commented Dec 21, 2011 at 18:29

4 Answers 4

7

As a general rule, don't use custom properties. You shouldn't modify DOM objects in ways they don't expect because they may not behave the way you think they will.

The mechanism for custom attributes in HTML5 is to use the data- prefix. If you use set/getAttribute for data- attributes, you should be OK as no standard attribute should be introduced in the future with a data- prefix (but other code in the page still might do so).

But having said that, I would still recommend using a custom object to store the values and referencing them by element id or class or some other standard (as in HTML 4.01) attribute value. It avoids the issue of custom properties and attributes and is known to work everywhere.

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

6 Comments

Can some check to see if this answer is up-to-date? Specifically, the line "HTML5 is not a standard and is not that widely implemented yet."
@MountainScott—per the HTML Living Standard: 'the term "HTML5" is widely used as a buzzword to refer to modern web technologies'. In 2011, it was not widely implemented. 10 years on, things are a little different. :-)
If things are different now, should you update the answer? and does the advice that using the data- attribute should be avoided still hold? I haven't noticed any reluctance in using it in javascript tutorials, so some clarity would be appreciated.
@MountainScott—answers should be considered in the context of when they were written. It's not realistic to expect answers to be updated for every related change to a web technology. Highly active answers are often updated by the community, I don't think this one falls into that basket. :-)
Not necessarily. Authors update and edit their responses all the time on this platform. The context of the question is enduring while the response...not so much. No one's forcing you to change, but it seemed advisable.
|
6

Well, there is the dataset property:

div.dataset.bar = 'baz';

but it's not implemented in IE.

Live demo: http://jsfiddle.net/simevidas/dJr2u/

4 Comments

Can we shim it in IE ? Is there any attempt at a shim?
i think this is a good solution, if dataset doesn't exist simply define it as a custom property.
dataset can only contain string values, since it's a bridge between DOM and data- attributes. It's good, but not enough for storing arbitary data connected to DOM elements.
this works, but weirdly if I set for example myobj.dataset.changed=true or false it doesn't seem to behave like a boolean and !myobj.dataset.changed always results into false instead of being inverted! So WTH?
1

This is what the specs say about the internal property accessors:

Host objects may implement these internal methods in any manner unless specified otherwise; for example, one possibility is that [[Get]] and [[Put]] for a particular host object indeed fetch and store property values but [[HasProperty]] always generates false.

and

Host objects may define additional constraints upon [[Put]] operations. If possible, host objects should not allow [[Put]] operations in situations where this definition of [[CanPut]] returns false.

However, I think this is just theoretical, and in reality expandos work as expected.

Comments

0

No.

Let's say 5 years ago you thought the property .contains was a good use-case for saying whether an element contained some special data.

So you wrote document.getElementById("someId").contains = true

Then you had checks like if (document.getElementByID("someId").contains)

Today that breaks because Node.prototype.contains is a method.

basically your code is not future safe.

4 Comments

Point taken. I remain curious as to whether it's present safe (ie would a browser be breaking the contract with the programmer if it did not support persisting custom properties).
@rampion I personally dont know of any implementations that do break
Though I guess he could use elem.data_contains or elem.dlkafh quite safely
Prefixing can solve this issue (for instance, it's highly unprobable that DOM spec eventually switches to snake_case, even if so, your code most likely will break by another reason). If prefixing is not good, Symbols solve collision issue totally.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.