在研究一個簡單的HTMLElement包裝器的想法時,我偶然發現了Internet Explorer和Chrome的如下內容: html
對於DOM樹中具備ID的給定HTMLElement,可使用其ID做爲變量名稱來檢索div。 因此對於像 html5
<div id="example">some text</div>
在Internet Explorer 8和Chrome中,您能夠執行如下操做: 數組
alert(example.innerHTML); //=> 'some text'
要麼 瀏覽器
alert(window['example'].innerHTML); //=> 'some text'
那麼,這是否意味着DOM樹中的每一個元素都將轉換爲全局名稱空間中的變量? 而且這是否還意味着能夠用它代替這些瀏覽器中的getElementById
方法? 緩存
如前面的答案中提到的,此行爲稱爲window對象上的命名訪問 。 某些元素的name
屬性值和全部元素的id
屬性值均可以用做全局window
對象的屬性。 這些被稱爲命名元素。 因爲window
是瀏覽器中的全局對象,所以每一個命名元素均可以做爲全局變量進行訪問。 安全
它最初是由Internet Explorer添加的,最終由全部其餘瀏覽器實現,只是爲了與依賴此行爲的網站兼容。 有趣的是,Gecko(Firefox的渲染引擎)選擇僅以怪癖模式實現此功能 ,而其餘渲染引擎則將其保留爲標準模式。 網絡
可是,從Firefox 14開始, Firefox如今還支持在標準模式下對window
對象的命名訪問 。 他們爲何要改變這一點? 事實證實,仍有不少站點在標準模式下依賴此功能。 微軟甚至發佈了一個行銷演示 ,阻止了該演示在Firefox中運行。 app
Webkit最近考慮了相反的作法,僅將window
對象上的命名訪問權限授予怪癖模式。 他們以與壁虎相同的理由決定反對。 dom
所以,……彷佛很瘋狂,由於從技術上講,如今在標準模式下的全部主流瀏覽器的最新版本中使用此行爲都是安全的 。 可是,儘管命名訪問彷佛有點方便, 但不該使用它 。 函數
爲何? 關於全局變量爲什麼壞的緣由,本文能夠總結不少緣由。 簡而言之,擁有大量額外的全局變量會致使更多錯誤。 假設您不當心輸入了var
的名稱,而碰巧輸入了DOM節點的id
,SURPRISE!
此外,儘管已標準化,但瀏覽器的命名訪問實現仍存在許多差別。
name
屬性的值可用於表單元素(輸入,選擇等)。 <a>
標記沒法經過其name
屬性訪問。 並且我敢確定,若是您嘗試在邊緣狀況下使用命名訪問,還會有更多。
如其餘答案中所述,請使用document.getElementById
經過其id
獲取對DOM節點的引用。 若是須要經過節點的name
屬性得到對節點的引用,請使用document.querySelectorAll
。
請,請不要經過在您的站點中使用命名訪問來傳播此問題。 所以,許多Web開發人員都在浪費時間嘗試跟蹤這種神奇的行爲。 咱們確實須要採起行動,並使渲染引擎在標準模式下關閉命名訪問。 從短時間來看,它將破壞一些作壞事的網站,但從長遠來看,它將幫助推進網絡向前發展。
若是您有興趣,請在個人博客-https: //www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/上更詳細地討論。
在這些狀況下,您應該堅持使用getElementById()
,例如:
document.getElementById('example').innerHTML
IE喜歡在全局名稱空間中混合使用具備name
和 ID
屬性的元素,所以最好明確說明您要獲取的內容。
應該發生的是添加了「命名元素」做爲document
對象的明顯屬性。 這是一個很是糟糕的主意,由於它容許元素名稱與document
實際屬性發生衝突。
IE也經過將命名元素添加爲window
對象的屬性來使狀況變得更糟。 這是雙重不利的,由於如今您必須避免在您想要使用的document
或window
對象(或項目中的任何其餘庫代碼)的任何成員以後命名元素。
這也意味着這些元素做爲全局變量可見。 幸運的是,在這種狀況下,代碼中的任何真實的全局var
或function
聲明都將它們遮蔽了,所以您沒必要擔憂在這裏命名,可是若是您嘗試使用名稱衝突的方式對全局變量進行賦值而忘記了若是將其聲明爲var
,則在IE中會出現錯誤,由於它試圖將值分配給元素自己。
一般,忽略var
以及依賴於在window
或全局變量上可見的命名元素是不明智的作法。 堅持使用document.getElementById
,它獲得了更普遍的支持,而且不那麼模棱兩可。 若是您不喜歡鍵入,則可使用短名稱編寫平凡的包裝函數。 不管哪一種方式,使用id到元素的查找緩存都是沒有意義的,由於瀏覽器一般會優化getElementById
調用以使用快速查找。 當元素更改id
或從文檔中添加/刪除元素時,您獲得的只是問題。
Opera複製了IE,而後加入了WebKit,如今HTML5 正在 標準化之前未標準化的將命名元素放在document
屬性中的作法,以及之前僅限IE將其放在window
中的作法,HTML5的作法是記錄和規範瀏覽器做者對咱們形成的全部可怕行爲,使它們永遠成爲網絡的一部分。 所以Firefox 4也將支持此功能。
什麼是「命名元素」? 具備id
任何事物,以及具備用於「識別」目的的name
事物:即表單,圖像,錨點和其餘一些事物,但沒有其餘不相關的name
屬性實例,例如表單輸入字段中的控件名稱, <param>
參數名稱或<meta>
元數據類型。 應該避免使用「標識」 name
來支持id
。
是的,他們有。
已在Chrome 55,Firefox 50,IE 11,IE Edge 14和Safari 10中測試
下面的例子:
<!DOCTYPE html> <html> <head> </head> <body> <div id="im_not_particularly_happy_with_that"> Hello World! </div> <script> im_not_particularly_happy_with_that.innerText = 'Hello Internet!'; </script> <!-- Looking at you W3 HTML5 spec group ಠ_ಠ --> </body> </html>
http://jsbin.com/mahobinopa/edit?html,輸出
這個問題聽起來應該是:「具備提供的ID的HTML標籤是否會成爲可全局訪問的DOM元素?」
答案是確定的!
這就是它的工做方式,這就是W3C最初引入ID的緣由。: 解析的腳本環境中的HTML Tag的ID成爲其對應的DOM元素句柄。
可是,Netscape Mozilla拒絕遵循(侵入他們的)W3C,並頑固地使用不推薦使用的Name屬性來形成破壞,所以破壞了W3C引入惟一ID所帶來的腳本功能和編碼便利性。
在Netscape Navigator 4.7慘敗以後,他們的開發人員全都去滲透了W3C,而他們的同事卻以錯誤的作法和錯誤的示例取代了Web。 強制使用和重用已通過時的Name屬性[!並非惟一的]與ID屬性相提並論,以便利用ID句柄訪問特定DOM元素的腳本會被破壞!
打破他們的作法,由於他們也會編寫和發佈大量的編碼課程和示例(他們的瀏覽器ElementID.property
沒法識別它們),例如document.all.ElementID.property
而不是ElementID.property
,至少使其效率低下,並給瀏覽器帶來更多開銷若是它不是簡單地在HTML域上經過使用相同的標記(如今[1996-97],已棄用)和爲其提供相同標記值的標準ID屬性來將其破壞的話。
他們很容易地說服了當時的絕大多數無知的代碼編寫愛好者,他們的名字和ID其實是相同的,除了ID屬性更短,所以比古老的Name屬性更節省字節和更方便編碼。 這固然是騙人的。 或者-在其取代已發表的HTML文章的過程當中,說服您須要爲標籤提供名稱和ID的文章,以便腳本引擎能夠訪問它們。
馬賽克殺手[代號「 Mozilla」]很是生氣,他們覺得「若是咱們失敗了,互聯網也應該如此」。
另外一方面,崛起的Microsoft太天真了,他們覺得應該保留不推薦使用的標記並標記爲刪除Name屬性,並將其視爲惟一標識符的ID來對待,以便他們不會破壞該腳本的腳本功能Netscape學員編碼的舊頁面。 他們是致命的錯誤...
並且,返回ID衝突元素的數組集合也不是解決此人爲問題的方法。 實際上,它戰勝了整個目標。
這是惟一的緣由W3C的越演越烈,給咱們idiocies如document.getElementById
和排序的陪同洛可可該死的煩人語法...(...)