DOM elements with ID's are global variables
Andrew Buntine Jan 12 '17
So, here is something weird.
Yesterday I was refactoring some code and came across something akin to this:
const logo = document.getElementById("brand") brand.style.top = 0
At no point in the codebase was a variable named
brand defined. And so any sane observer would expect that the preceding snippet would result in a runtime error -- assuming there was not something like a linter available that would have picked up on it (and the fact that
logo was being defined but never used) first.
I started having one of those moments that we all dread: I was looking at some code that could not possibly have ever worked. Yet, there it was. Working. I sank into my chair, not sure to make of what I was seeing.
So I changed it:
<div id="brand_foo"> ... </div>
And then, lo and behold, the code instantly started causing a runtime error. Wait. No way... The browser is surely not pre-defining a global variable for each DOM element with an ID attribute. Right?
Wrong! It does. I've looked at this code in most major browsers and mobile devices and not one of them complained.
Don't believe me? You can try it yourself right now. Press F12 (or otherwise Right Click -> Inspect), find an element with an ID, and then evaluate that ID at the console REPL.
window["brand-name"] // --> <div id="brand-name">
I have no idea how well known this is. I certainly did not know about it but, admittedly, I haven't spent a lot of time in the browser in many years. I've reached out to all of the frontend developers I know and none of them knew about this either.
As it turns out, the HTML specification actually documents this functionality. Although it seems major browsers are not implementing it uniformly at all. If you define more than one element with the same ID (you evil person), then Chrome will actually return an array of
Element objects whilst Firefox returns the first element it saw. And neither browsers define global variables based on the
name attribute on elements like
Should I make use of this?
No. Please, no. Imagine how confusing this could get if you were dealing with many DOM elements in a non-trivial codebase and none of them were being defined anywhere visible to the programmer. Or imagine if you go all-in and then one day a major browser decides this is insanity and disables it!
The only place I can see this being of use would be in the REPL whilst debugging. But, still, it's kind of cool in a never-do-this kind of way.
Header image originally from http://www.classichorrorcampaign.com