原文:http://www.2ality.com/2012/08/ids-are-global.html
有人在twitter上提到了:在Chrome的JavaScript終端中,你只需要輸入一個元素的ID,就可以訪問到這個元素.@johnjbarton給了解釋,這是因為所有的元素ID都是全局變量.本文再詳細解釋一下.
標准規范
HTML5規范文檔中指出:如果一個元素符合下面兩條規則中的任一條,則window對象中必須要有與之對應的一個屬性,屬性值就是這個對象.
- 如果一個元素擁有ID屬性,那么ID屬性的屬性值就會成為window對象的屬性名.
- 如果一個元素擁有name屬性,那么name屬性的屬性值就會成為window對象的屬性名.但這個元素的標簽名必須是: a, applet, area, embed, form, frame, frameset, iframe, img, object,其中的一個.
讓我們看一個例子.假定存在一個頁面,該頁面包含了一個ID屬性為“foo”的div元素:
<div id="foo"></div>
這樣一來,上面的的div元素就可以通過window.foo(和其他的window屬性一樣),或者全局變量foo來訪問到.比如,在Chrome控制台中,你可以這樣做:
> "foo" in window true > foo <div id="foo"></div>
Firefox
火狐(14)的工作方式略有不同.
> "foo" in window false > typeof foo // 這個全局變量到底有木有? object
//錯誤控制台輸出了下面的警告.
//Element referenced by ID/NAME in the global scope. //Use W3C standard document.getElementById() instead. > foo [object HTMLDivElement]
//錯誤控制台輸出了下面的警告.
//Element referenced by ID/NAME in the global scope. //Use W3C standard document.getElementById() instead.
> "foo" in window
true
這到底是怎么一回事?初始化時,window並沒有屬性foo.但在第一次訪問這個屬性的時候(通過window.foo屬性直接訪問或者通過全局變量foo來訪問都可以),它會被自動建立.
譯者注:我在Firefox14,15,18中都沒有發現警告,不過在Firefox12試驗時,的確有警告.
[注意:例子中的代碼只能在網頁中通過script標簽運行才能見效,不能通過終端運行.這是因為終端在處理全局對象時,使用了不同的方式.]
譯者注:我在Firebug中嘗試例子中的代碼,並沒發現有什么差別.
一旦你嘗試讀取foo的值,雖然會正常返回那個div元素,但同時錯誤控制台會有警告,告訴你不應該那么做.很顯然,這樣的警告是正確的:在終端調試的時候,你可以使用這個特性,但在實際的代碼中,不應該使用.
Cody Lindley寫了一個jsPerf測試來比較通過全局變量訪問foo和通過window.foo來訪問foo的性能差別.有趣的是,只有在Firefox中訪問window.foo更快點.