65

All browsers I've come to work with allow accessing an element with id="myDiv" by simply writing:

myDiv

See here: http://jsfiddle.net/L91q54Lt/

Anyway, this method seems to be quite poorly documented, and in fact, the sources I come across don't even give it a mention and instead assume that one would use

document.getElementById("myDiv")

or maybe

document.querySelector("#myDiv")

to access a DOM element even when its ID is known in advance (i.e. not calculated at runtime). I can tell that the latter approaches have the advantage of keeping the code safe if someone inadvertedly attempts to redefine myDiv in a wider scope (not such a brilliant idea though...), overwrites it with some different value and goes on without noticing the clash.

But other that that? Are there any concerns in using the short form above other than code design, or what else am I missing here?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
GOTO 0
  • 42,323
  • 22
  • 125
  • 158
  • 11
    a window-property (like `myDiv`) may be anything(note that it may be overwritten), but `getElementById` returns the HTMLElement(regardless of the value of the property) – Dr.Molle Aug 15 '14 at 11:01
  • Building apps, web pages that use the ID as the indicator is bar far a better approach. designing an app where the use of getElementById is maximized, as oppose to $(..find-something) or querySelector is supreme in performance. Even if during your app, you assign uuid's to elements so that they can be located rapidly, or better still cache them. – MartinWebb Aug 15 '14 at 11:04
  • 3
    @Jack: that question doesn’t mention accessing HTML elements with IDs via global variables, which is what this question is about. So I don’t think “highly related” is quite right. – Paul D. Waite Aug 15 '14 at 11:07
  • @Jack: maybe. If you can find a duplicate, feel free to post it. – Paul D. Waite Aug 15 '14 at 11:10
  • 5
    Closely related: http://stackoverflow.com/questions/3434278/ie-chrome-are-dom-tree-elements-global-variables-here – Qantas 94 Heavy Aug 15 '14 at 11:25
  • @PaulD.Waite That wouldn't have been necessary if you had diverted your answering efforts into finding a duplicate instead; in any case, Qantas found it. – Ja͢ck Aug 15 '14 at 11:56
  • 1
    @Jack: maybe. I think it would have been more effort to find that duplicate than write the answer. And note that the duplicate question only brings up the issue that this question is asking about in its very last sentence. When reading it and its answers, you’ve got to wade through the initial stuff (is this feature supported by all browsers?) before getting to the answer to this question (why is doing this a bad idea?). “Don’t repeat yourself” is a great principle for programming. It’s not a universal constant. Duplication isn’t always evil. – Paul D. Waite Aug 15 '14 at 12:30
  • Another related question: http://stackoverflow.com/questions/7826737/directly-reference-html-elements – Ja͢ck Aug 15 '14 at 12:30
  • There are great answers to this question in the answers to 3434278 though — much better than mine. – Paul D. Waite Aug 15 '14 at 12:32
  • @PaulD.Waite I agree that finding a proper dupe wasn't entirely trivial, my reasoning is that doing so gives due credit to those who have answered before ... that doesn't prohibit anyone from answering anyway, and if their answer is better, that'd be great :) – Ja͢ck Aug 15 '14 at 12:32
  • 1
    @Jack: ah, due credit. The Rightful Spoils of “First!”. Yeah, it’s worth doing. But if answering is quick, the OP gets their answer quickly, and if there are different wordings of similar questions, I think that means there’s a better chance that someone asking the same question again will get a match in the auto-search. – Paul D. Waite Aug 15 '14 at 12:35
  • Not sure what constitutes "quite poorly documented," but it's in both the WHATWG spec and the W3C HTML 5.1 spec. – johncip Feb 26 '19 at 06:48

5 Answers5

51

Anyway, this method seems to be quite poorly documented, and In fact, the sources I come across don't even give it a mention [...]

Reliance on implicitly-declared global variables aside, the lack of documentation is a great reason not to use it.

The apparent promotion of id values into global variables isn't standards compliant (the HTML5 spec for the ID attribute doesn't mention it) and, therefore, you shouldn't assume future browsers will implement it.

EDIT: It turns out this behaviour is standards compliant - In HTML5, window should support property access to "Named Elements":

Named objects with the name name, for the purposes of the above algorithm, are those that are either:

  • child browsing contexts of the active document whose name is name,
  • a, applet, area, embed, form, frameset, img, or object elements that have a name content attribute whose value is name, or
  • HTML elements that have an id content attribute whose value is name.

Source: HTML 5 spec, 'Named access on window object", emphasis mine.

Based on this, standards compliance is not a reason to avoid this pattern. However, the spec itself advises against its use:

As a general rule, relying on this will lead to brittle code. Which IDs end up mapping to this API can vary over time, as new features are added to the Web platform, for example. Instead of this, use document.getElementById() or document.querySelector().

loa_in_
  • 1,030
  • 9
  • 20
joews
  • 29,767
  • 10
  • 79
  • 91
  • 22
    Why would the spec specify something then advise against using it?! As if the web needs more bad practices. #facepalm# – Songo Aug 15 '14 at 14:56
  • 9
    I'd guess as a way of formalising support for legacy patterns that have fallen into common(ish) usage. – joews Aug 15 '14 at 14:59
  • 2
    AFAIK `name != id` (necessarily) , I never found any documentation explicitly stating that you cannot have 1 element with name="foo" and another with id="foo" (could have missed it), so 1 more level of ambiguity. I didn't see the point in both name and id - until separating them broke a bunch of stuff in GTK3's API (specifically gtkbuilder xml UIs). – technosaurus Aug 16 '14 at 03:31
  • 2
    @Izkata I know, wouldn't you rather learn from others mistakes. Much of gtkbuilder and gtk3 styling was modeled after html and css, then when they decided that javascript would be a 1st class language for building gtk3 apps, they modified the old behavior which had been name~=id and broke a lot of stuff ... the ability to reference both name and id as globals is very similar and I would suspect that in a future edition either name goes away altogether or name gets the global treatment (lots of legacy forms for non-js browsers depend on it) and id would need to be acquired (just speculation). – technosaurus Aug 16 '14 at 04:17
  • @technosaurus Your comment was just very non-sequitur and initially seemed to be trying to apply a completely different language/framework to the question/answer. For example, elements with `name="foo"` are not accessible by name in the same namespace as elements with `id="foo"`, so there is no ambiguity. – Izkata Aug 16 '14 at 05:53
  • @Izkata that's exactly one of the problems with this "feature" - it -_does_ make elements accessible by id and name in the same way. – joews Aug 16 '14 at 06:07
  • @joews Go to the jsfiddle in the question, change `id="myDiv"` to `name="myDiv"`, re-run it and try the first button. It does not work in Firefox or Chrome (even after changing it to an `a` tag as the second bullet suggests). – Izkata Aug 16 '14 at 07:35
  • @joews The HTML5 spec (section 5.2.4 Named access on the Window object) validates the shorthand use of ids without assigning them to vars. I searched the spec looking for a reference to 'brittle code' but there was none. Presumably the spec has been updated since your comments on Aug 15 '14 at 11:04. – BlackMagic Aug 28 '15 at 13:27
  • 3
    Given the edit and the update, I am not seeing a reason to not use this feature. – ESR Aug 28 '17 at 03:05
  • @BlackMagic - It's in the [WHATWG Living Standard (7.3.3 Named access on the Window object)](https://html.spec.whatwg.org/multipage/window-object.html#named-access-on-the-window-object), not the HTML5 standard. [They are very similar](https://en.wikipedia.org/wiki/HTML#WHATWG_HTML_versus_HTML5), but the standards are published by almost entirely separate groups. The [advice I've read](http://www.brucelawson.co.uk/2014/on-html5-vs-living-standard-w3c-vs-whatwg/) says to look at HTML5 for current state, and at Living Standard for where browsers are headed. – JDB Dec 04 '17 at 22:28
21

Great question. As Einstein probably didn’t say, things should be as simple as possible, and no simpler.

the latter approaches have the advantage of keeping the code safe if someone inadvertedly attempts to redefine myDiv in a wider scope (not such a brilliant idea though...), overwrites it with some different value and goes on without noticing the clash

That’s the main reason why this is a bad idea, and it’s quite enough. Global variables aren’t safe to rely on. They can be overwritten at any time, by any script that ends up running on the page.

In addition to that, just typing in myDiv isn’t a “short form” of document.getElementById(). It’s a reference to a global variable.document.getElementById() will happily return null if the element doesn’t exist, whilst attempting to access a non-existent global variable will throw a reference error, so you’d need to wrap your references to the global in a try/catch block to be safe.

This is one reason why jQuery is so popular: if you do $("#myDiv").remove(), and there is no element with an id of myDiv, no error will be thrown — the code will just silently do nothing, which is often exactly what you want when doing DOM manipulation.

Paul D. Waite
  • 96,640
  • 56
  • 199
  • 270
16

There are a few reasons:

You don't want your code and your markup that coupled.

By using a specific call to access a div, you don't have to worry about the global space being corrupted. Add a library that declares myDiv in global space and you're in a world of pain that will be hard to fix.

You can access elements, by ID, that aren't part of the DOM

They can be in a fragment, a frame, or an element that has been detached and not re-attached to the DOM yet.

EDIT: Example of accessing a non-attached elements by ID

var frag = document.createDocumentFragment();
var span = document.createElement("span");
span.id = "span-test";
frag.appendChild(span);
var span2 = frag.getElementById("span-test");
alert(span === span2);
Jeremy J Starcher
  • 23,369
  • 6
  • 54
  • 74
  • 1
    It looks like you're wrong: neither Firefox nor Chromium allows me to *access elements, by ID, that aren't part of the DOM*. At least detached ones. – user Aug 15 '14 at 21:49
  • @user You can't access them using `document.getElementById`, however, I updated my answer to show how to access a `span`, by `id`, inside of a `documentFragment`. – Jeremy J Starcher Aug 15 '14 at 22:01
  • I name all my ids in `UPPERCASE_ID`, that grealy reduces the chance of a collision, and makes them more id'entifiable. – run_the_race Sep 06 '22 at 08:46
2

In my case I had an iframe inside my page. I was confused by id attribute vs name attribute, both of which affected a variable named inner_iframe, accessible from window!

  • If I used only the id attribute, like id="inner_iframe", window.inner_iframe is a HTMLIFrameElement. Properties include inner_iframe.contentDocument and inner_iframe.contentWindow as described here*

  • If I used only the name attribute, like name="inner_iframe" then window.inner_iframe is a "frame", aka a "window object". contentWindow, therefore the name-attribute inner_iframe does not have properties contentDocument or contentWindow.

  • If I used both name and id attributes, and I gave both attributes the same value name="inner_iframe" id="inner-iframe"; the name attribute trumped/clobbered the id attribute; I was left with the "window object", not the HTMLIFrameElement!

So my point is to be careful about ambiguity; the conflict between name and id attributes on the same object with two different APIs: is just a specific case where implicit behavior and attachment to a window variable may confuse you.

*(and only if the <script> was loaded after/beneath the <iframe> in the HTML, or the <script> waited until window.onload before trying to access by id attribute)

**this "frame" vs DOM Element distinction is described in Mozilla documentation as:

Each item in the window.frames pseudo-array represents the window object corresponding to the given 's or 's content, not the (i)frame DOM element (i.e., window.frames[0] is the same thing as document.getElementsByTagName("iframe")[0].contentWindow).

Nate Anderson
  • 18,334
  • 18
  • 100
  • 135
1

As someone that has been developing Web-based applications for over 25 years, I can say with certainty that the only reason for this quirky behavior is backwards compatibility.

The method getElementById wasn't even part of DOM Level 1. However, the earlier DOM Level 0 allowed direct access to most elements on the page:

https://docstore.mik.ua/orelly/webprog/dhtml/ch02_04.htm

As you can see, browsers like Netscape 6 and MSIE 5 continued to support the old convention, even after getElementById was adopted as a "standard"

The earliest DHTML capable browsers like Netscape Navigator and MSIE frequently pushed their own DOM specs into the marketplace. So you ended up with a lot of bad design decisions which ultimately became standardized by virtue of "that's how it was done before".

https://www.quirksmode.org/js/dom0.html

For reasons of backward compatibility the more advanced browsers, even those who support the Level 1 DOM, still also support the old, faithful Level 0 DOM. Not supporting it would mean that the most common scripts suddenly wouldn't work any more. So even though the Level 0 DOM doesn't entirely fit into the new DOM concepts, browsers will continue to support it.

When Netscape introduced Level 0 DOM, it was likely assumed that Web-based applications would never amount to more than auto-filling a few form fields and moving some images around the screen. So there was no concern about polluting the global window object with a handful of element IDs.

Obviously that solution didn't scale well at all. But we're stuck with this archaic Level 0 DOM convention just so as not to break legacy Javascript code.

Leslie Krause
  • 387
  • 3
  • 4