具备ID的DOM树元素是否会成为全局变量?

在研究一个简单的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方法? 缓存


#1楼

如前面的答案中提到的,此行为称为window对象上的命名访问 。 某些元素的name属性值和全部元素的id属性值均可以用做全局window对象的属性。 这些被称为命名元素。 因为window是浏览器中的全局对象,所以每一个命名元素均可以做为全局变量进行访问。 安全

它最初是由Internet Explorer添加的,最终由全部其余浏览器实现,只是为了与依赖此行为的网站兼容。 有趣的是,Gecko(Firefox的渲染引擎)选择仅以怪癖模式实现此功能 ,而其余渲染引擎则将其保留为标准模式。 网络

可是,从Firefox 14开始, Firefox如今还支持在标准模式下对window对象的命名访问 。 他们为何要改变这一点? 事实证实,仍有不少站点在标准模式下依赖此功能。 微软甚至发布了一个行销演示 ,阻止了该演示在Firefox中运行。 app

Webkit最近考虑了相反的作法,仅将window对象上的命名访问权限授予怪癖模式。 他们以与壁虎相同的理由决定反对。 dom

所以,……彷佛很疯狂,由于从技术上讲,如今在标准模式下的全部主流浏览器的最新版本中使用此行为都是安全的 。 可是,尽管命名访问彷佛有点方便, 但不该使用它函数

为何? 关于全局变量为什么坏的缘由,本文能够总结不少缘由。 简而言之,拥有大量额外的全局变量会致使更多错误。 假设您不当心输入了var的名称,而碰巧输入了DOM节点的id ,SURPRISE!

此外,尽管已标准化,但浏览器的命名访问实现仍存在许多差别。

  • IE错误地使name属性的值可用于表单元素(输入,选择等)。
  • Gecko和Webkit错误地使<a>标记没法经过其name属性访问。
  • Gecko错误地处理了多个具备相同名称的命名元素(它返回对单个节点的引用,而不是引用数组)。

并且我敢确定,若是您尝试在边缘状况下使用命名访问,还会有更多。

如其余答案中所述,请使用document.getElementById经过其id获取对DOM节点的引用。 若是须要经过节点的name属性得到对节点的引用,请使用document.querySelectorAll

请,请不要经过在您的站点中使用命名访问来传播此问题。 所以,许多Web开发人员都在浪费时间尝试跟踪这种神奇的行为。 咱们确实须要采起行动,并使渲染引擎在标准模式下关闭命名访问。 从短时间来看,它将破坏一些作坏事的网站,但从长远来看,它将帮助推进网络向前发展。

若是您有兴趣,请在个人博客-https: //www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/上更详细地讨论。


#2楼

在这些状况下,您应该坚持使用getElementById() ,例如:

document.getElementById('example').innerHTML

IE喜欢在全局名称空间中混合使用具备name ID属性的元素,所以最好明确说明您要获取的内容。


#3楼

应该发生的是添加了“命名元素”做为document对象的明显属性。 这是一个很是糟糕的主意,由于它容许元素名称与document实际属性发生冲突。

IE也经过将命名元素添加为window对象的属性来使状况变得更糟。 这是双重不利的,由于如今您必须避免在您想要使用的documentwindow对象(或项目中的任何其余库代码)的任何成员以后命名元素。

这也意味着这些元素做为全局变量可见。 幸运的是,在这种状况下,代码中的任何真实的全局varfunction声明都将它们遮蔽了,所以您没必要担忧在这里命名,可是若是您尝试使用名称冲突的方式对全局变量进行赋值而忘记了若是将其声明为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


#4楼

是的,他们有。

已在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,输出


#5楼

这个问题听起来应该是:“具备提供的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和排序的陪同洛可可该死的烦人语法...(...)

相关文章
相关标签/搜索