DOM elements with ID's are global variables
Tags: javascript, dom, browsers
Published: 2017-01-12 13:07:23

---
title: DOM elements with ID's are global variables
permalink: dom-elements-with-ids-are-global-variables
published: true
description: The browser defines a global variable for each ID in your HTML document.
cover_image: http://i.imgur.com/UrJb8y9.jpg
tags: javascript, dom, browsers
---

So, here is something weird.

Yesterday I was refactoring some code and came across something akin to this:

```javascript
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.

In fact, the only other place I could see the word "brand" in the entire application was in the HTML document upon which this Javascript was being executed (yes, some websites still send HTML over the wire).

So I changed it:

```html
<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.

What about IDs such as "brand-name" that don't conform to Javascript's grammar? Surely they are ignored? Nope:

```javascript
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](https://html.spec.whatwg.org/#named-access-on-the-window-object). 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 `img` and `a`.

## 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*