做IDS DOM树元素成为全局变量?

问题描述 投票:329回答:5

工作的一个想法简单的HTML元素的包装,我偶然发现的Internet Explorer和Chrome如下:

对于在DOM树ID给定的HTML元素,可以使用其ID作为变量名称检索股利。因此,对于像一个div

<div id="example">some text</div>

Internet Explorer 8和Chrome,你可以这样做:

alert(example.innerHTML); //=> 'some text'

要么

alert(window['example'].innerHTML); //=> 'some text'

那么,这是否意味着在DOM树中的每个元素被转换成一个变量在全局命名空间?而且它也意味着我们可以以此为在这些浏览器的getElementById方法更换?

javascript dom global-variables getelementbyid identifier
5个回答
375
投票

什么是应该发生的是“命名的元素”被添加作为document对象的表观性质。这是一个非常糟糕的主意,因为它允许元素名称与document的不动产冲突。

IE也通过添加命名的元素作为window对象的属性使情况更糟。这是极为糟糕的,现在你必须避免无论是documentwindow对象,你(或项目中的任何其他库的代码)的任何成员后命名您的元素可能需要使用。

这也意味着,这些元素是作为全球变量一样可见。幸运的是,在这种情况下,你的代码中的任何真正的全球varfunction声明影子,所以你不必担心命名这里这么多,但如果你试图做一个赋值给一个全局变量有冲突的名字,你忘了声明一下var,你会因为它试图赋值元素本身获得的IE错误。

它通常被认为是不好的做法,省去var,以及依靠命名的元素是在window或全局可见。坚持document.getElementById,这是更广泛的支持和更加明确。你可以写一个简单的包装功能,用较短的名字,如果你不喜欢打字。无论哪种方式,有在用一个id到元素查找高速缓存是没有意义的,因为浏览器通常优化getElementById呼叫仍要使用快速查找;你得到的是问题,当元素改变id或添加/从文件中删除。

歌剧复制IE,然后WebKit的加入进来,现在都穿上document属性命名的元素,并把它们放在window先前-IE-只有实践以前不标准的做法是通过HTML5 being standardised,其方法是将文件和通过标准化浏览器作者遭受我们每一个可怕的做法,使他们永远是网络中的一部分。所以,火狐4也将支持这一点。

什么是“命名的元素”?被用于“标识”的宗旨任何与一个id,并用name任何内容:即,表格,图像,锚和其他几个,但一个name属性的不其它无关的情况下,像在表单输入字段控制名称,参数名称在<param> <meta>或元数据的类型。 “确定” names是应该应该有利于id来避免的。


46
投票

由于在前面的答复中提到这种行为被称为named access on the window object。对于一些元素name属性,所有元素的id属性值的值可用作为全球window对象的属性。这些被称为命名的元素。由于window是在浏览器中的全局对象,每个命名的元素将是作为一个全局变量访问。

这原本是由Internet Explorer增加,并最终被所有其他浏览器只是用于依赖于这种行为的网站兼容性实现。有趣的是,壁虎(Firefox的渲染引擎)选择了只quirks mode实现这一点,而其他渲染引擎在标准模式下离开它。

然而,如火狐14,在标准模式下的Firefox now supports named access对象上window为好。他们为什么要改变呢?原来还是有很多依赖于在标准模式下,此功能的网站。微软甚至released a marketing demo该做,防止演示在Firefox工作。

Webkit的有最近considered the opposite,在退居对象window上唯一的怪癖模式命名访问。他们决定反对由同样理由壁虎。

所以......疯了,因为它似乎这种行为现在是技术上安全的在标准模式下,所有的主流浏览器的最新版本为使用。不过,虽然命名访问能似乎有点方便,它不应该被使用。

为什么?很多推理可以这篇文章为什么global variables are bad中总结出来的。简单地说,有一堆额外的全局变量会导致更多的错误。比方说,你不小心键入var的名称,碰巧键入一个DOM节点,惊喜的id

此外,尽管被标准化还存在的命名访问浏览器实现了不少的差异。

  • IE错误地使name属性的值表单元素(输入,选择等)可访问的。
  • 壁虎和Webkit正确不作<a>标签通过他们name属性访问。
  • 壁虎错误地处理具有相同名称(它返回到单个节点,而不是引用数组的引用)多个命名的元素。

而且我敢肯定有更多,如果你尝试使用在边缘情形上命名访问。

正如在其他的答案中提到使用document.getElementByIdid得到一个DOM节点的引用。如果你需要得到其name到节点的属性参考使用document.querySelectorAll

拜托,请不要在你的网站使用命名访问传播这一问题。因此,许多Web开发人员浪费时间去追查这片神奇的行为。我们真的需要采取行动,并得到渲染引擎打开命名访问关闭的标准模式。在短期内它会打破一些网站做坏事,但是从长远来看,它会有助于推进网络。

如果你有兴趣我谈得更详细些我的博客上 - https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/


20
投票

你应该坚持在这些情况下getElementById(),例如:

document.getElementById('example').innerHTML

IE喜欢混搭与name元素和属性ID在全局命名空间,所以最好是明确约你要得到什么。


3
投票

是的,他们做的。

测试在Chrome 55,火狐50,IE 11,IE边缘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,output


2
投票

这个问题应该声音::“你的HTML标签所提供的ID成为全球访问DOM元素?”

答案是肯定的!

这就是它的意思是如何工作的,这就是为什么标识是由W3C介绍开始:HTML标记的在解析脚本环境的ID成为其对应的DOM元素手柄。

不过,网景的Mozilla拒绝遵从(他们侵入)W3C固执地使用过时的名称属性来制造混乱,并因此打破了脚本功能,并通过W3C的推出唯一ID带来了方便编码保存。

在Netscape Navigator中4.7惨败后,他们的开发人员都去了,并渗透到W3C,而他们的同伙用浪的错误做法和滥用的例子网络。与ID强制标准杆已经过时名称属性[!这是不是意味着是唯一】的使用和再利用的属性,使得利用ID的脚本处理访问特定的DOM元素只会突破!

并打破他们做了,因为他们也撰写和发表大量的编码的经验教训和例子[他们的浏览器将不会反正承认]如document.all.ElementID.property代替ElementID.property至少使其效率低下,给浏览器更多的开销的情况下,它没有简单地休息它在通过使用用于(现在[1996-97],不建议使用)名称相同的令牌和标准ID属性具有相同的令牌值供给它HTML域。

他们轻松地设法说服 - 那时 - 无知的代码编写业余名称和ID实际上是相同的压倒性的军队,除了ID属性更短,因此字节节约型,更方便的编码器比古代名称属性。这当然是一个谎言。或者 - 在其替代HTML发表文章,有说服力的,你需要同时提供姓名和身份证到您的标签他们是由脚本引擎访问文章。

马赛克杀手[代号为“Mozilla的”]是如此生气,他们认为:“如果我们下去,所以要上网”。

上升的微软 - 在另一方面 - 是如此的天真,他们认为他们应该继续不推荐使用,并标记为删除Name属性,并把它当作好像它是一个ID是唯一标识,所以他们不会打破的脚本功能旧网页由Netscape学员编码。他们是致命的错误......

和任一ID冲突的元件的阵列集合的返回没有一个解决这个蓄意人为问题。实际上,它击败了全部目的。

这是唯一的原因W3C的越演越烈,给我们idiocies如document.getElementById和排序的伴随洛可可该死的烦人语法...(...)

© www.soinside.com 2019 - 2024. All rights reserved.