在构思一个简单的 HTMLElement
包装器时,我偶然发现了 Internet Explorer 和 Chrome 的以下内容:
对于 DOM 树中带有 id
的给定 HTMLElement
,可以使用其 ID 作为变量名或作为 window
的属性来检索 <div>
。所以对于 <div>
喜欢
<div id="example">some text</div>
在 Internet Explorer 8 和 Chrome 中,您可以:
alert(example.innerHTML); // Alerts "some text".
或者
alert(window["example"].innerHTML); // Alerts "some text".
那么,这是否意味着 DOM 树中的每个元素 都被转换为全局对象的属性?这是否也意味着可以在这些浏览器中使用它来替代 getElementById
方法?
应该发生的是“命名元素”作为 document
对象的明显属性添加。这是一个非常糟糕的主意,因为它允许元素名称与 document
的真实属性发生冲突。
IE 通过添加命名元素作为 window
对象的属性使情况变得更糟。这是双重不利的,因为现在您必须避免以您(或您项目中的任何其他库代码)可能想要使用的 document
或 window
对象的任何成员命名您的元素。
这也意味着这些元素作为类全局变量可见。幸运的是,在这种情况下,您的代码中的任何真正的全局 var
或 function
声明都会影响它们,因此您不必担心这里的命名,但如果您尝试对全局变量进行分配时会产生冲突name 并且您忘记声明它 var
,您将在 IE 中收到错误,因为它试图将值分配给元素本身。
通常认为省略 var
以及依赖命名元素在 window
上可见或作为全局元素是不好的做法。坚持 document.getElementById
,它得到了更广泛的支持并且不那么模棱两可。如果您不喜欢打字,您可以编写一个名称较短的简单包装函数。无论哪种方式,都没有必要使用 id-to-element 查找缓存,因为浏览器通常会优化 getElementById
调用以使用快速查找;当元素更改 id
或从文档中添加/删除时,您得到的只是问题。
Opera 复制了 IE,然后 WebKit 加入,现在将命名元素放在 document
属性上的以前未标准化的做法和将它们放在 window
上的以前仅限 IE 的做法是 being standardised HTML5,它的方法是记录和标准化浏览器作者对我们施加的每一个可怕的做法,使它们永远成为网络的一部分。所以 Firefox 4 也将支持这一点。
什么是“命名元素”?任何带有 id
的东西和任何带有 name
的东西都被用于“识别”目的:即表单、图像、锚点和其他一些,但不包括 name
属性的其他不相关实例,如 control-表单输入字段中的名称、<param>
中的参数名称或 <meta>
中的元数据类型。 “识别”name
是应该避免使用 id
的。
如前面的答案所述,此行为称为 named access on the window object。某些元素的 name
属性值和所有元素的 id
属性值都可用作全局 window
对象的属性。这些被称为命名元素。由于 window
是浏览器中的全局对象,每个命名元素都可以作为全局变量访问。
这最初是由 Internet Explorer 添加的,最终由所有其他浏览器实现,只是为了与依赖此行为的站点兼容。有趣的是,Gecko(Firefox 的渲染引擎)选择仅在 quirks mode 中实现这一点,而其他渲染引擎将其保留在标准模式下。
但是,从 Firefox 14 开始,标准模式下的 window
对象上的 Firefox now supports named access 也是如此。他们为什么要改变这个?事实证明,仍然有很多网站在标准模式下依赖此功能。微软甚至 released a marketing demo 这样做了,阻止了演示在 Firefox 中运行。
Webkit 最近有 considered the opposite,将 window
对象的命名访问权限降级为仅怪癖模式。他们以与壁虎相同的理由决定反对它。
所以……疯狂,因为现在这种行为在标准模式下在所有主要浏览器的最新版本中使用在技术上是安全的。但是,虽然命名访问看起来有些方便,但不应该使用它。
为什么?关于为什么global variables are bad,这篇文章可以总结出很多推理。简单地说,拥有一堆额外的全局变量会导致更多的错误。假设您不小心输入了 var
的名称,并且碰巧输入了 DOM 节点的 id
,SURPRISE!
此外,尽管已经标准化,浏览器的命名访问实现仍然存在不少差异。
IE 错误地使表单元素(输入、选择等)可以访问 name 属性的值。
Gecko 和 Webkit 错误地没有使 标记可以通过它们的 name 属性访问。
Gecko 错误地处理了多个具有相同名称的命名元素(它返回对单个节点的引用而不是引用数组)。
如果您尝试在边缘情况下使用命名访问,我敢肯定还有更多。
如其他答案中所述,使用 document.getElementById
通过其 id
获取对 DOM 节点的引用。如果您需要通过节点的 name
属性获取对节点的引用,请使用 document.querySelectorAll
。
请不要通过在您的站点中使用命名访问来传播此问题。如此多的 Web 开发人员浪费时间试图追踪这种神奇的行为。我们真的需要采取行动,让渲染引擎在标准模式下关闭命名访问。在短期内,它会破坏一些做坏事的网站,但从长远来看,它将有助于推动网络向前发展。
如果您有兴趣,我会在我的博客 - https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/ 上更详细地讨论这个问题。
document.querySelectorAll
和 document.querySelector
。 +1 为使用它的好建议。通过选择器访问元素绝对是一个更高效的过程。
getElementsByClassName
等比 getElementById
慢两倍
在这些情况下,您应该坚持使用 getElementById()
,例如:
document.getElementById('example').innerHTML
IE 喜欢在全局命名空间中混合具有 name
和 ID
属性的元素,因此最好明确说明您想要获取的内容。
这个问题听起来应该是:“带有提供 ID 的 HTML 标签会成为全球可访问的 DOM 元素吗?”
答案是肯定的!
这就是它的工作方式,这也是 W3C 一开始就引入 ID 的原因。:解析脚本环境中 HTML 标记的 ID 成为其对应的 DOM 元素句柄。
然而,Netscape Mozilla 拒绝遵守(对他们侵入)W3C 并顽固地使用已弃用的 Name 属性来造成严重破坏,因此破坏了 W3C 引入唯一 ID 带来的脚本功能和编码便利性。
在 Netscape Navigator 4.7 惨败之后,他们的开发人员都潜入了 W3C,而他们的同事则以错误的做法和滥用示例来取代 Web。强制使用和重用已弃用的 Name 属性 [!which 不意味着是唯一的] 与 ID 属性相提并论,这样使用 ID 句柄访问特定 DOM 元素的脚本就会崩溃!
并且打破他们所做的,因为他们还将编写和发布大量的编码课程和示例 [他们的浏览器无论如何都无法识别],例如 document.all.ElementID.property
而不是 ElementID.property
至少使其效率低下并给浏览器更多开销以防万一'不要简单地通过对(现在 [1996-97],已弃用)名称和标准 ID 属性使用相同的标记来破坏它在 HTML 域中为它提供相同的标记值。
他们轻松地说服了——当时——压倒性的无知代码编写爱好者大军,名称和 ID 实际上是相同的,除了 ID 属性更短,因此比古老的 Name 属性更节省字节并且对编码器更方便。这当然是谎言。或者 - 在他们取代已发布的 HTML 文章中,令人信服的文章表明您需要为您的标签提供名称和 ID,以便脚本引擎可以访问它们。
Mosaic Killers [代号“Mozilla”] 非常生气,他们认为“如果我们倒闭,互联网也应该如此”。
另一方面,崛起的微软非常天真,他们认为应该保留已弃用并标记为删除的 Name 属性,并将其视为唯一标识符的 ID,这样他们就不会破坏脚本功能由 Netscape 学员编码的旧页面。他们大错特错...
并且返回 ID 冲突元素的数组集合也不能解决这个故意的人为问题。实际上它破坏了整个目的。
这是 W3C 变得丑陋并给我们带来诸如 document.getElementById
之类的白痴以及伴随的那种该死的洛可可式烦人语法的唯一原因...(...)
是的,他们有。
通过以下示例在 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,output
window
对象访问它们:window["first-name"]
不定期副业成功案例分享