Koo*_*Inc 341 javascript dom global-variables identifier getelementbyid
研究一个简单的HTMLElement包装器的想法我偶然发现了Internet Explorer和Chrome的以下内容:
对于DOM树中具有ID的给定HTMLElement,可以使用其ID作为变量名来检索div.所以对于一个喜欢的div
<div id="example">some text</div>
Run Code Online (Sandbox Code Playgroud)
在Internet Explorer 8和Chrome中,您可以执行以下操作:
alert(example.innerHTML); //=> 'some text'
Run Code Online (Sandbox Code Playgroud)
要么
alert(window['example'].innerHTML); //=> 'some text'
Run Code Online (Sandbox Code Playgroud)
那么,这是否意味着DOM树中的每个元素都转换为全局命名空间中的变量?它是否也意味着可以使用它作为getElementById
这些浏览器中方法的替代品?
bob*_*nce 380
应该发生的是"命名元素"被添加为document
对象的表观属性.这是一个非常糟糕的主意,因为它允许元素名称与真实属性冲突document
.
IE通过添加命名元素作为window
对象的属性使情况变得更糟.这是非常糟糕的,因为现在您必须避免document
在window
您(或项目中的任何其他库代码)可能想要使用的对象的任何成员之后命名您的元素.
它还意味着这些元素作为类似全局的变量可见.幸运的是,在这种情况下,代码中的任何真正的全局var
或function
声明都会影响它们,因此您不必担心这里的命名,但如果您尝试对具有冲突名称的全局变量进行赋值而忘记声明它var
,你会在IE中得到一个错误,因为它试图将值赋给元素本身.
通常认为不好的做法是省略var
,以及依赖于在window
全局上可见的命名元素.坚持document.getElementById
,更广泛支持,更少模糊.如果您不喜欢打字,可以使用较短的名称编写一个简单的包装函数.无论哪种方式,使用id-to-element查找缓存都没有意义,因为浏览器通常会优化getElementById
调用以使用快速查找; 所有你得到的是元素更改id
或从文档中添加/删除时出现的问题.
歌剧复制IE,然后WebKit的加入进来,现在都穿上命名元素的以前不标准,实践document
特性,并把他们的先前IE-只有实践window
都被 标准化的HTML5,其方法是将文件和规范每浏览器作者给我们带来了可怕的做法,使它们永远成为网络的一部分.所以Firefox 4也会支持这个.
什么是'命名元素'?任何带有一个id
东西,以及name
用于"识别"目的的任何东西:即形式,图像,锚点和其他一些东西,但不是name
属性的其他无关实例,例如表单输入字段中的控件名称,参数名称<param>
或元数据类型<meta>
.'识别' name
是应该避免的id
.
TJ *_*oll 49
如前面的答案所述,此行为称为窗口对象上的命名访问.该值name
的某些元素属性和值id
的所有元素的属性都可用作为全球性质window
的对象.这些被称为命名元素.由于window
是浏览器中的全局对象,因此每个命名元素都可以作为全局变量访问.
这最初是由Internet Explorer添加的,最终由所有其他浏览器实现,仅仅是为了与依赖于此行为的站点兼容.有趣的是,Gecko(Firefox的渲染引擎)选择仅以怪癖模式实现此功能,而其他渲染引擎则以标准模式启用它.
然而,像Firefox 14,火狐现在支持命名访问上window
的标准模式对象也是如此.他们为什么改变这个?事实证明,仍有很多网站在标准模式下依赖此功能.微软甚至发布了一个营销演示,阻止了该演示在Firefox中运行.
Webkit最近考虑了相反的做法,window
仅将对象的命名访问权限降级为怪癖模式.他们通过与Gecko相同的推理决定反对它.
所以...疯狂,因为看起来这种行为现在在标准模式下的所有主流浏览器的最新版本中使用在技术上是安全的.但是虽然命名访问看起来有点方便,但不应该使用它.
为什么?本文总结了很多关于全局变量为什么不好的原因.简而言之,拥有一堆额外的全局变量会导致更多错误.假设您不小心输入了a的名称var
并碰巧键入了id
一个DOM节点,SURPRISE!
此外,尽管标准化,但浏览器的命名访问实现仍然存在很多差异.
name
表单元素(输入,选择等)可以访问属性的值.<a>
通过其name
属性访问标签.如果你尝试在边缘情况下使用命名访问,我相信还有更多.
正如其他答案中所提到的那样,document.getElementById
用来获取对DOM节点的引用id
.如果需要通过其name
属性使用来获取对节点的引用document.querySelectorAll
.
请不要在您的站点中使用命名访问来传播此问题.如此多的网络开发人员浪费时间试图追踪这种神奇的行为.我们确实需要采取行动并让渲染引擎在标准模式下关闭命名访问.从短期来看,它会破坏一些做坏事的网站,但从长远来看,这将有助于推动网络向前发展.
如果您有兴趣,我可以在我的博客上更详细地讨论这个问题 - https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/.
Nic*_*ver 20
getElementById()
在这些情况下你应该坚持,例如:
document.getElementById('example').innerHTML
Run Code Online (Sandbox Code Playgroud)
IE喜欢在全局命名空间中混合使用元素name
和 ID
属性,因此最好明确指出你想要获得的内容.
这个问题听起来应该是:“带有提供 ID 的 HTML 标签会成为全局可访问的 DOM 元素吗?”
答案是肯定的!
这就是它的工作原理,这就是 W3C 开始引入 ID 的原因。: 解析脚本环境中的 HTML 标记的 ID 成为其对应的 DOM 元素句柄。
然而,Netscape Mozilla 拒绝遵守(对他们来说是侵入性的)W3C 并顽固地继续使用已弃用的 Name 属性来制造破坏,因此破坏了 W3C 引入唯一 ID 带来的脚本功能和编码便利。
在 Netscape Navigator 4.7 惨败之后,他们的开发人员都去渗透了 W3C,而他们的同事正在以错误的做法和滥用示例取代 Web。强制使用和重用已弃用的 Name 属性 [! 这并不意味着是唯一的] 与 ID 属性相同,这样使用 ID 句柄访问特定 DOM 元素的脚本就会崩溃!
并打破他们做了,因为他们也撰写和发表大量的编码的经验教训和例子[他们的浏览器将不会反正承认]例如 document.all.ElementID.property
,而不是ElementID.property
至少使其效率低下,更多的开销给浏览器的情况下,它没有简单地打破它HTML 域使用相同的标记(现在 [1996-97],已弃用)名称和标准 ID 属性为其提供相同的标记值。
他们很容易地说服了当时压倒性的无知的代码编写爱好者大军,Names 和 ID 实际上是相同的,除了 ID 属性更短,因此比古老的 Name 属性更节省字节并且对编码人员更方便。这当然是谎言。或者 - 在他们取代已发布的 HTML 文章中,说服文章您需要为标签提供名称和 ID,以便脚本引擎可以访问它们。
Mosaic Killers [代号为“Mozilla”] 非常生气,他们认为“如果我们失败了,互联网也应该如此”。
另一方面,崛起的微软太天真了,他们认为他们应该保留已弃用并标记为删除的 Name 属性,并将其视为唯一标识符的 ID,这样他们就不会破坏脚本功能Netscape 受训人员编码的旧页面。他们大错特错……
并且返回 ID 冲突元素的数组集合也不是解决这个故意人为问题的方法。事实上,它违背了整个目的。
这就是 W3C 变得丑陋并给我们带来了诸如document.getElementById
洛可可式这种令人讨厌的洛可可式语法之类的白痴的唯一原因......(......)
是的,他们确实这么做了。
\n\n在 Chrome 55、Firefox 50、IE 11、IE Edge 14 和 Safari 10 中测试
\n并使用以下示例:
<!DOCTYPE html>\n<html>\n<head>\n</head>\n<body>\n <div id="im_not_particularly_happy_with_that">\n Hello World!\n </div>\n <script>\n im_not_particularly_happy_with_that.innerText = \'Hello Internet!\';\n </script>\n <!-- Looking at you W3 HTML5 spec group \xe0\xb2\xa0_\xe0\xb2\xa0 -->\n</body>\n</html>\n
Run Code Online (Sandbox Code Playgroud)\n\nhttp://jsbin.com/mahobinopa/edit?html,输出
\n