首頁 > 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
作者最新文章
最新問題
相關專題
更多>
熱門推薦
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板