0

It's my understanding that every modern browser, both desktop and mobile, surfaces elements with IDs to the global JavaScript namespace. Still, people all over the industry keep using document.getElementById() or its jQuery cousin $("#TheID").

For cases that are not pathological (e. g. ID that matches another object in the global namespace), is there any reason for doing so, other than misplaced concern for backwards compatibility? How far back in time do you have to go so that it starts mattering?

EDIT: consider the following:

<html>
<body>
<input type="hidden" id="Foo" value="Hello world"/>
<input type="button" onclick="alert(Foo.value);" value="Press this"/>
</body>
</html>

It displays "Hello world" on MSIE on Windows, Chrome, Firefox, Opera, Safari on Mac, Safari on iPad, Android browser, MSIE on Windows Phone... Why would anybody use document.getElementById("Foo").value instead?

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • 1
    I have no idea what you're actually asking. – Jecoms Sep 13 '16 at 00:37
  • 1
    What if external scripts that you include create variables with IDs that happen to be the same as element IDs on your page? You might not even notice, at first... Regarding `$("#TheID")`, the point of that is that it lets you use the various jQuery methods on the result. – nnnnnn Sep 13 '16 at 00:39
  • Also see http://stackoverflow.com/questions/8862665/what-does-it-mean-global-namespace-would-be-polluted – Phil Sep 13 '16 at 00:44
  • Despite being borderline off-topic, upvoted due to this being the potential cause of many problems if used. – 3ocene Sep 13 '16 at 00:50
  • @Jecoms, the edit seems to be a little easier to understand. – 3ocene Sep 13 '16 at 00:50
  • @Bern Yeah, I see what he is suggesting now. Seems like a maintenance nightmare. – Jecoms Sep 13 '16 at 00:52
  • 2
    If you have literally a six-line html document with no script elements as shown in the edit then there isn't much that can go wrong, but a real-world page rarely looks that simple, and if the page is later expanded and script elements are added then one of the scripts might have a `Foo` variable of its own. Then what? It's best practice to keep global variables to a minimum, but still in the event that you decide you "need" one for something you shouldn't have to worry about whether the name might be the same as something in the HTML. – nnnnnn Sep 13 '16 at 00:57

2 Answers2

3

For cases that are not pathological (e. g. ID that matches another object in the global namespace)…

Because literally any variable could be added to the global namespace, there is no case that are "not pathalogical".

is there any reason for doing so, other than misplaced concern for backwards compatibility?

By convention we avoid introducing global variables that would otherwise conflict with existing global variables (e.x. we don't declare var document or var setTimeout). In fact, it's generally recommended that you avoid introducing any global variables at all by enclosing them in a scope somewhere.

If you were to do otherwise you will quickly run into maintenance issues. Maintenance issues that don't scale.

Consider the case where you have an element with [id="question"]. If you rely on the global reference of question to refer to that element, and someone else working on your project decides to introduce a question.js module elsewhere, you're going to have a really hard time debugging the issue.

The intent behind referencing question the DOM node will be unclear, and the means of accessing the element are equally unclear.

Furthermore, how do you handle the case where the ID changes? If you use document.getElementById(...) you will need to store a reference to the DOM node. If the ID changes, you'll only have to update the selector in one place.

If you start making use of the global reference to the DOM node, you'll need to update all the usages.

The reasons for avoiding global references to DOM nodes has nothing to do with compatibility, and everything to do with the fact that it's a terrible feature.

zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • It's worth noting the readability factor as well. `foo` could be anything (string, int, object, etc) whereas document.getElementById("foo") will either be a DOM object or undefined. – 3ocene Sep 13 '16 at 00:46
  • 1
    @Bern, DOM node or `null` actually; but yes, the point that it serves as a data contract stands. – zzzzBov Sep 13 '16 at 00:47
  • @Bern - It won't be undefined; it might be null. But you are correct about readability - even where the result is assigned to a variable you can trace that just by reading the JS, you don't have to also search through the HTML. – nnnnnn Sep 13 '16 at 00:47
  • The answer assumes a certain structure of the page and the project - a huge page with numerous poorly written and poorly understood 3rd party dependencies, maintained by a team that doesn't communicate :) Still, point taken. – Seva Alekseyev Sep 13 '16 at 00:56
  • 1
    @SevaAlekseyev, "a huge page" consider a large site with many interchangeable modules that may or may not exist. "that doesn't communicate" consider a large codebase that is constantly changing. The point is not that the team isn't communicating or that the pages are large. The point is that *the team doesn't have to waste time* sharing unnecessary trivial details and **the project is flexible** enough to undergo drastic changes with minimal negative effects. – zzzzBov Sep 13 '16 at 01:00
0

Another reason might be performance. Referencing document only once is the preferred way, as far as I know. See 10 Javascript Performance Boosting Tips from Nicholas Zakas 1. Define local variables

In other words:

var doc = document;
var btn = doc.getElementById('myButton');
var img = doc.getElementById('myImage');

whereas

var btn = myButton;
var img = myImage;

has to lookup to document twice.

Ronnie Royston
  • 16,778
  • 6
  • 77
  • 91