使用ID做DOM树元素成为全局变量?
处理一个简单的HTMLElement包装的想法我偶然发现了以下的Internet Explorer和Chrome:
对于在DOM树中具有ID的给定HTMLElement,可以使用其ID作为变量名来检索div。 所以对于一个div来说
<div id="example">some text</div>
在Internet Explorer 8和Chrome中,您可以执行以下操作:
alert(example.innerHTML); //=> 'some text'
要么
alert(window['example'].innerHTML); //=> 'some text'
那么,这是否意味着DOM树中的每个元素都转换为全局命名空间中的变量? 这是否也意味着可以使用它作为这些浏览器中的getElementById
方法的替代品?
应该发生的是'命名元素'被添加为document
对象的明显属性。 这是一个非常糟糕的主意,因为它允许元素名称与document
真实属性发生冲突。
IE通过添加命名元素作为window
对象的属性而使情况变得更糟。 这是非常糟糕的,因为现在你必须避免在document
或window
对象的任何成员(或者项目中的任何其他库代码)可能想要使用的元素之后命名元素。
这也意味着这些元素可以看作是类似全局的变量。 幸运的是,在这种情况下,任何真正的全球var
或function
在你的代码中的声明阴影,所以你不必担心命名这里这么多,但如果你试图做一个赋值给一个全局变量有冲突的名字,你忘了要声明它var
,你会在IE中看到一个错误,因为它试图将值赋给元素本身。
通常认为忽略var
以及依赖于在window
中可见的命名元素或全局变量被认为是不好的做法。 坚持document.getElementById
,这是更广泛支持和不太模糊。 如果你不喜欢打字,你可以用较短的名字编写一个简单的包装函数。 无论哪种方式,使用ID到元素的查找缓存都没有意义,因为浏览器通常会优化getElementById
调用以使用快速查找; 当元素更改id
或者从文档中添加/删除元素时,您所得到的只是问题。
Opera拷贝了IE,然后加入了WebKit,而现在这两种先前未标准化的将命名元素放在document
属性上的做法,以及以前仅将IE放在window
上的IE做法都正在通过HTML5进行标准化,HTML5的方法是将文档标准化浏览器作者对我们造成的每一个可怕的做法,使他们永远成为网络的一部分。 所以Firefox 4也会支持这一点。
什么是'命名元素'? 任何带有id
东西,以及任何name
都用于“识别”的目的:即表单,图像,锚点和其他一些,但不包含name
属性的其他无关实例,如表单输入字段中的控件名称, <param>
参数名称或<meta>
元数据类型。 '识别' name
是应该避免使用id
。
正如在前面的答案中提到的,这种行为在窗口对象上被称为命名访问。 某些元素的name
属性值和所有元素的id
属性值可用作全局window
对象的属性。 这些被称为命名元素。 由于window
是浏览器中的全局对象,因此每个命名元素都可以作为全局变量访问。
这最初由Internet Explorer添加,并最终由所有其他浏览器实现,仅用于与依赖此行为的网站的兼容性。 有趣的是,Gecko(Firefox的渲染引擎)选择只在怪癖模式下实现,而其他渲染引擎将其置于标准模式。
但是,从Firefox 14开始,Firefox现在也支持标准模式下window
对象的命名访问。 他们为什么改变这个? 原来仍然有很多网站在标准模式下依赖这种功能。 微软甚至发布了一个营销演示,阻止了演示在Firefox中运行。
Webkit最近考虑了相反的情况,将window
对象的命名访问仅限于quirks模式。 他们通过与壁虎相同的推理决定了它。
所以......疯狂,因为看起来这种行为现在在标准模式下在所有主流浏览器的最新版本中使用在技术上是安全的 。 虽然命名访问看起来有点方便, 但不应该使用 。
为什么? 在这篇文章中可以总结出很多理由,说明为什么全局变量很糟糕。 简而言之,拥有一堆额外的全局变量会导致更多的错误。 假设你不小心键入了一个var
的名字,而且恰好键入了一个DOM节点的id
,那么惊喜!
另外,尽管被标准化,浏览器的命名访问实现仍然存在很多差异。
name
属性的值可访问。 name
属性来访问<a>
标签。 而且我敢肯定还有更多,如果你尝试在边缘情况下使用命名访问。
正如在其他答案中提到的,使用document.getElementById
通过其id
来获取对DOM节点的引用。 如果您需要通过其name
属性获取对节点的引用,请使用document.querySelectorAll
。
请不要通过在您的网站中使用命名访问来传播此问题。 许多Web开发人员浪费时间来追踪这种神奇的行为。 我们确实需要采取行动并让渲染引擎在标准模式下关闭命名访问。 在短期内,它会打破一些网站做坏事,但从长远来看,它将有助于网络向前发展。
如果你有兴趣,我可以在我的博客上更详细地讨论这个问题 - http://tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/。
在这些情况下,您应该坚持getElementById()
,例如:
document.getElementById('example').innerHTML
IE喜欢在全局命名空间中混合具有name
和ID
属性的元素,所以最好明确您想要获得的内容。
上一篇: Do DOM tree elements with ids become global variables?
下一篇: Google analytics is showing Internet explorer 7 for following user agent. Why?