使用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对象的属性而使情况变得更糟。 这是非常糟糕的,因为现在你必须避免在documentwindow对象的任何成员(或者项目中的任何其他库代码)可能想要使用的元素之后命名元素。

这也意味着这些元素可以看作是类似全局的变量。 幸运的是,在这种情况下,任何真正的全球varfunction在你的代码中的声明阴影,所以你不必担心命名这里这么多,但如果你试图做一个赋值给一个全局变量有冲突的名字,你忘了要声明它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 ,那么惊喜!

另外,尽管被标准化,浏览器的命名访问实现仍然存在很多差异。

  • IE错误地使表单元素(输入,选择等)的name属性的值可访问。
  • Gecko和Webkit不正确地不通过它们的name属性来访问<a>标签。
  • Gecko不正确地处理具有相同名称的多个命名元素(它返回对单个节点的引用而不是引用数组)。
  • 而且我敢肯定还有更多,如果你尝试在边缘情况下使用命名访问。

    正如在其他答案中提到的,使用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喜欢在全局命名空间中混合具有nameID属性的元素,所以最好明确您想要获得的内容。

    链接地址: http://www.djcxy.com/p/51903.html

    上一篇: Do DOM tree elements with ids become global variables?

    下一篇: Google analytics is showing Internet explorer 7 for following user agent. Why?