首页 > web前端 > css教程 > 命名元素ID可以称为JavaScript Globals

命名元素ID可以称为JavaScript Globals

尊渡假赌尊渡假赌尊渡假赌
发布: 2025-03-10 11:18:15
原创
751 人浏览过

Named Element IDs Can Be Referenced as JavaScript Globals

您知道吗?带有ID的DOM元素可在JavaScript中作为全局变量访问?这是一个存在已久的功能,但我才第一次深入研究它。

如果您第一次听说这个功能,请做好准备!只需在HTML中向元素添加ID,我们就可以看到它在实际中的应用:

<div id="cool"></div>
登录后复制
登录后复制

通常,我们会使用querySelector("#cool")getElementById("cool")定义一个新变量来选择该元素:

var el = querySelector("#cool");
登录后复制
登录后复制

但实际上,我们无需这些繁琐的操作就能访问#cool

因此,HTML中的任何ID(或name属性)都可以在JavaScript中使用window[ELEMENT_ID]访问。再次强调,这并非“新”功能,但很少见。

正如您可能猜到的那样,使用命名引用访问全局作用域并非最佳方案。有些人称其为“全局作用域污染者”。我们将探讨原因,但首先……

一些背景

这种方法在HTML规范中有所描述,其中将其描述为“Window对象的命名访问”。

Internet Explorer是第一个实现此功能的浏览器。其他浏览器也添加了此功能。当时,Gecko是唯一一个不直接在标准模式下支持它的浏览器,而是选择将其作为实验性功能。人们对是否实现它犹豫不决,但为了浏览器的兼容性,它最终得以推进(Gecko甚至试图说服WebKit将其从标准模式中移除),并最终在Firefox 14中进入标准模式。

可能鲜为人知的一点是,浏览器不得不采取一些预防措施(成功程度各不相同),以确保生成的全局变量不会破坏网页。其中一项措施是……

变量遮蔽

此功能最有趣的部分可能是命名元素引用不会遮蔽现有的全局变量。因此,如果DOM元素的ID已定义为全局变量,它不会覆盖现有的变量。例如:

window.foo = "bar";
登录后复制
登录后复制
<div id="foo">I won't override window.foo</div>
登录后复制
console.log(window.foo); // 输出 "bar"
登录后复制

反之亦然:

<div id="foo">I will be overridden :(</div>
登录后复制
window.foo = "bar";
console.log(window.foo); // 输出 "bar"
登录后复制

此行为至关重要,因为它可以消除危险的覆盖,例如<div id="alert"></div>,否则它会通过使alert API失效而造成冲突。这种保护技术很可能是您(如果您像我一样)第一次了解它的原因。

反对命名全局变量的论据

前面我说过,使用命名全局元素作为引用可能并非最佳方案。有很多原因,TJ VanToll在他的博客中对此进行了很好的阐述,我将在此处总结:

  • 如果DOM发生更改,则引用也会更改。 这使得代码非常“脆弱”(规范中的术语),HTML和JavaScript之间的关注点分离可能过于严格。
  • 意外引用过于容易。 一个简单的错字很可能会引用一个命名全局变量,并给您带来意想不到的结果。
  • 在不同的浏览器中实现方式不同。 例如,我们应该能够访问具有ID的锚点(例如<a><code><a></a>),但某些浏览器(即Safari和Firefox)会在控制台中返回ReferenceError。
  • 它可能不会返回您认为的结果。 根据规范,当DOM中存在多个相同命名元素的实例时(例如,两个<div><code><div>实例),浏览器应该返回一个包含这些实例数组的HTMLCollection。但是,Firefox只返回第一个实例。再说一次,规范指出我们应该在元素树中使用一个ID实例。但是这样做不会阻止页面工作或任何类似的事情。 <li> <strong>可能有性能成本?</strong> 我的意思是,浏览器必须创建该引用列表并维护它。一些人在StackOverflow线程中运行了测试,其中命名全局变量在一个测试中实际上性能更高,而在最近的测试中性能较低。</li> <h3>其他注意事项</h3> <p>假设我们抛弃了反对使用命名全局变量的批评,并继续使用它们。一切顺利。但是,在您这样做时,您可能需要考虑一些事情。</p> <h4>polyfills</h4> <p>听起来可能很极端,但这些类型的全局检查是polyfills的典型设置要求。查看以下示例,我们使用新的CookieStore API设置cookie,在尚不支持它的浏览器中对其进行polyfill:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">&lt;div id=&quot;cool&quot;&gt;&lt;/div&gt;</pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>这段代码在Chrome中运行良好,但在Safari中会抛出以下错误:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">var el = querySelector(&quot;#cool&quot;);</pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>在撰写本文时,Safari不支持CookieStore API。因此,polyfill不会应用,因为img元素ID会创建一个与cookieStore全局变量冲突的全局变量。</p> <h4>JavaScript API更新</h4> <p>我们可以改变情况,找到另一个问题,即浏览器JavaScript引擎的更新可能会破坏命名元素的全局引用。</p> <p>例如:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">window.foo = &quot;bar&quot;;</pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>该脚本获取对输入元素的引用,并在其上调用focus()。它可以正常工作。但是,我们不知道它还能工作多久。</p> <p>您会看到,我们用来引用输入元素的全局变量一旦浏览器开始支持BarcodeDetector API就会停止工作。那时,window.BarcodeDetector全局变量将不再是输入元素的引用,而.focus()将抛出“window.BarcodeDetector.focus is not a function”错误。</p> <h3>结论</h3> <p>让我们总结一下我们是如何走到这一步的:</p> <ul> <li>所有主要浏览器都会自动创建对每个具有id(或在某些情况下为name属性)的DOM元素的全局引用。</li> <li>通过其全局引用访问这些元素是不可靠的,并且可能很危险。请改用<code>querySelectorgetElementById
  • 由于全局引用是自动生成的,它们可能会对您的代码产生一些副作用。这是一个避免使用id属性的好理由,除非您确实需要它。

最终,最好避免在JavaScript中使用命名全局变量。我前面引用了规范中关于它会导致“脆弱”代码的内容,但以下是完整的文本,以强调这一点:

一般来说,依赖于此会导致脆弱的代码。随着时间的推移,哪些ID最终映射到此API可能会发生变化,例如,随着新功能添加到Web平台。不要这样做,请使用document.getElementById()document.querySelector()

我认为HTML规范本身建议避免使用此功能就说明了一切。

以上是命名元素ID可以称为JavaScript Globals的详细内容。更多信息请关注PHP中文网其他相关文章!

上一篇:在前端的WordPress块中渲染外部API数据 下一篇:CSS网格和自定义形状,第3部分
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
最新问题
相关专题
更多>
热门推荐
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板