24

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?

rampion
  • 82,104
  • 41
  • 185
  • 301
  • 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). – Marc B Oct 25 '11 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). – Šime Vidas Oct 25 '11 at 20:43
  • Looks like it does. http://jsfiddle.net/YJAvP/ – Birey Oct 25 '11 at 20:45
  • @Šime Vidas: Good to know! Then I suppose I should ask - are we guaranteed that the same host object will be returned when referring to the same semantic node? And that any custom properties set through javascript will be maintained? – rampion Oct 25 '11 at 20:46
  • 1
    @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. – Šime Vidas Oct 25 '11 at 21:09
  • You may want to use Jquery data() method which overcomes the browser incompatibilities – Raghav Oct 25 '11 at 21:22
  • 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"? – user123444555621 Oct 25 '11 at 21:24
  • @Pumbaa80: By "semantic node" I suppose I meant "logical node" - defined not by what is stored in memory and where, but why where it is in the tree and what it contains. The DOM is a black box to me - I don't know what it's doing behind the scenes. DOM element - I suppose I mean "node in the DOM tree". And I think you're misparsing that last sentence. I'll try again: "Does the DOM API guarantee that its methods will return the same javascript object when referring to the same DOM node?" – rampion Oct 25 '11 at 21:37
  • @Marc B: jQuery adds a property to the node with a name like `jQuery164017400505682040923` (an object with the same name will be present on the window) which has a value of type Number (e.g. `node.jQuery164017400505682040923 = 1`). It doesn't really matter if you use `node.__myData` or `node.jquery...`. The only benefit i see is that if you use `innerHTML` or similar methods/properties the memory leak might not be as big as with `node.__myData = { /* many properties*/ }` – Saxoier Oct 25 '11 at 22:57
  • 1
    possible duplicate of [Can I add arbitrary properties to DOM objects?](http://stackoverflow.com/questions/4258466/can-i-add-arbitrary-properties-to-dom-objects) – Lightness Races in Orbit Dec 21 '11 at 18:29

4 Answers4

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.

However, HTML5 is not a stanard and is not that widely implemented yet. But if you use set/getAttribute for data- attributes it should work on all reasonably modern browsers and no standard attribute should be introduced in the future with a data- prefix.

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.

handle
  • 5,063
  • 2
  • 40
  • 69
RobG
  • 124,520
  • 28
  • 153
  • 188
  • 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." – Mountain Scott Mar 13 '21 at 08:10
  • @MountainScott—per the [*HTML Living Standard*](https://html.spec.whatwg.org/#is-this-html5?): '*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. :-) – RobG Mar 13 '21 at 21:16
  • 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. – Mountain Scott Mar 19 '21 at 19:58
  • @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. :-) – RobG Mar 22 '21 at 21:50
  • 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. – Mountain Scott Mar 26 '21 at 22:11
5

Well, there is the dataset property:

div.dataset.bar = 'baz';

but it's not implemented in IE.

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

Šime Vidas
  • 163,768
  • 59
  • 261
  • 366
  • Can we shim it in IE ? Is there any attempt at a shim? – Raynos Oct 25 '11 at 20:54
  • i think this is a good solution, if dataset doesn't exist simply define it as a custom property. – Ibu Oct 26 '11 at 00:59
  • 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. – Strider Aug 09 '19 at 14:41
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.

user123444555621
  • 130,762
  • 25
  • 104
  • 122
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.

Raynos
  • 156,883
  • 55
  • 337
  • 385
  • 2
    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 Oct 25 '11 at 20:56
  • @rampion I personally dont know of any implementations that do break – Raynos Oct 25 '11 at 20:56
  • 1
    Though I guess he could use `elem.data_contains` or `elem.dlkafh` quite safely – oriadam Aug 01 '16 at 09:13
  • 1
    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. – Strider Aug 09 '19 at 14:45