带有 ID 的 DOM 元素是全局变量

2025-06-04

带有 ID 的 DOM 元素是全局变量

所以,这里有一些奇怪的事情。

昨天我正在重构一些代码并遇到了类似这样的情况:

const logo = document.getElementById("brand")

brand.style.top = 0
Enter fullscreen mode Exit fullscreen mode

代码库中从未出现过名为brand“defined”的变量。因此,任何理智的观察者都会认为上述代码片段会导致运行时错误——假设没有类似 Linter 之类的工具能够logo首先发现它(以及它被定义但从未被使用的事实)。

我开始经历一种我们都害怕的时刻:我看到一些根本不可能运行的代码。然而,它就在那里,运行着。我瘫坐在椅子上,不知道该如何理解眼前的一切。

事实上,在整个应用程序中我唯一能看到“品牌”这个词的地方是在执行此 Javascript 的 HTML 文档中(是的,一些网站仍然通过网络发送 HTML)。

所以我改变了它:

<div id="brand_foo"> ... </div>
Enter fullscreen mode Exit fullscreen mode

然后,瞧,代码立刻开始引发运行时错误。等等。不可能吧……浏览器肯定不会为每个带有 ID 属性的 DOM 元素预先定义一个全局变量吧?对吧?

错了!确实如此。我在大多数主流浏览器和移动设备上都测试过这段代码,没有一个出现问题。

不相信?现在就可以自己尝试一下。按 F12(或者右键单击 -> 检查),找到一个带有 ID 的元素,然后在控制台 REPL 中执行该 ID。

那么像“brand-name”这样不符合 JavaScript 语法的 ID 怎么办呢?它们肯定会被忽略吗?当然不会:

window["brand-name"]  // --> <div id="brand-name">
Enter fullscreen mode Exit fullscreen mode

我不知道这个功能有多出名。我当然不知道,但坦白说,我已经很多年没怎么在浏览器上花过时间了。我联系了所有我认识的前端开发者,但他们也都不知道这个功能。

事实证明,HTML 规范确实记录了此功能。尽管主流浏览器似乎并未统一实现它。如果你使用相同的 ID 定义多个元素(你这个恶人),Chrome 实际上会返回一个对象数组,而ElementFirefox 则会返回它看到的第一个元素。而且,这两个浏览器都没有根据name元素的属性(例如imga)定义全局变量。

我应该利用这个吗?

不,千万不要。想象一下,如果你在一个复杂的代码库中处理大量 DOM 元素,而它们中任何一个都没有在程序员可见的地方定义,那会多么令人困惑。或者想象一下,如果你全力以赴,然后有一天,一个主流浏览器认为这太疯狂了,并禁用了它!

我认为唯一能用到这个的地方就是在 REPL 里调试的时候。不过,这玩意儿用起来还是挺酷的,虽然我不太喜欢用这个。

标题图片最初来自http://www.classichorrorcampaign.com

文章来源:https://dev.to/buntine/dom-elements-with-ids-are-global-variables
PREV
Top 5 Data Visualization Libraries You Should Know in 2025
NEXT
Web 开发人员的顶级工具