Javascript 带有 id 的 DOM 树元素会成为全局变量吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 
原文地址: http://stackoverflow.com/questions/3434278/
Warning: these are provided under cc-by-sa 4.0 license.  You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Do DOM tree elements with ids become global variables?
提问by KooiInc
Working on an idea for a simple HTMLElement wrapper I stumbled upon the following for Internet Explorer and Chrome:
在研究一个简单的 HTMLElement 包装器的想法时,我偶然发现了 Internet Explorer 和Chrome的以下内容:
For a given HTMLElement with ID in the DOM tree, it is possible to retrieve the div using its ID as the variable name. So for a div like
对于 DOM 树中具有 ID 的给定 HTMLElement,可以使用其 ID 作为变量名来检索 div。所以对于像这样的 div
<div id="example">some text</div>
in Internet Explorer 8and Chrome you can do:
在Internet Explorer 8和 Chrome 中,您可以执行以下操作:
alert(example.innerHTML); //=> 'some text'
or
或者
alert(window['example'].innerHTML); //=> 'some text'
So, does this mean every element in the DOM treeis converted to a variable in the global namespace? And does it also mean one can use this as a replacement for the getElementByIdmethod in these browsers?
那么,这是否意味着DOM 树中的每个元素都被转换为全局命名空间中的变量?这是否也意味着人们可以使用它来替代getElementById这些浏览器中的方法?
回答by bobince
What is supposed to happen is that ‘named elements' are added as apparent properties of the documentobject. This is a really bad idea, as it allows element names to clash with real properties of document.
应该发生的是“命名元素”被添加为document对象的明显属性。这是一个非常糟糕的主意,因为它允许元素名称与document.
IE made the situation worse by also adding named elements as properties of the windowobject. This is doubly bad in that now you have to avoid naming your elements after any member of either the documentor the windowobject you (or any other library code in your project) might want to use.
IE 还通过添加命名元素作为window对象的属性使情况变得更糟。这很糟糕,因为现在您必须避免document以window您(或您项目中的任何其他库代码)可能想要使用的对象或对象的任何成员命名您的元素。
It also means that these elements are visible as global-like variables. Luckily in this case any real global varor functiondeclarations in your code shadow them, so you don't need to worry so much about naming here, but if you try to do an assignment to a global variable with a clashing name and you forget to declare it var, you'll get an error in IE as it tries to assign the value to the element itself.
这也意味着这些元素作为全局变量可见。幸运的是,在这种情况下,代码中的任何真正的全局变量var或function声明都会影响它们,因此您不必担心在此处命名,但是如果您尝试对具有冲突名称的全局变量进行赋值而忘记声明它var,您将在 IE 中收到错误,因为它试图将值分配给元素本身。
It's generally considered bad practice to omit var, as well as to rely on named elements being visible on windowor as globals. Stick to document.getElementById, which is more widely-supported and less ambiguous. You can write a trivial wrapper function with a shorter name if you don't like the typing. Either way, there's no point in using an id-to-element lookup cache, because browsers typically optimise the getElementByIdcall to use a quick lookup anyway; all you get is problems when elements change idor are added/removed from the document.
省略var以及依赖于在window全局变量上可见或作为全局变量可见的命名元素通常被认为是不好的做法。坚持document.getElementById,这是更广泛的支持和更少的歧义。如果您不喜欢打字,您可以使用较短的名称编写一个简单的包装函数。无论哪种方式,使用 id-to-element 查找缓存都没有意义,因为浏览器通常会优化getElementById调用以使用快速查找;当元素更改id或从文档中添加/删除时,您所得到的只是问题。
Opera copied IE, then WebKit joined in, and now both the previously-unstandardised practice of putting named elements on documentproperties, and the previously-IE-only practice of putting them on windoware beingstandardisedby HTML5, whose approach is to document and standardise every terrible practice inflicted on us by browser authors, making them part of the web forever. So Firefox 4 will also support this.
Opera 复制了 IE,然后加入了 WebKit,现在,以前未标准化的将命名元素放在document属性上的做法,以及以前仅在 IE 上放置它们的做法window都被HTML5标准化了,HTML5 的方法是记录和标准化每个浏览器作者强加给我们的可怕做法,使他们永远成为网络的一部分。所以Firefox 4 也将支持这一点。
What are ‘named elements'? Anything with an id, and anything with a namebeing used for ‘identifying' purposes: that is, forms, images, anchors and a few others, but not other unrelated instances of a nameattribute, like control-names in form input fields, parameter names in <param>or metadata type in <meta>. ‘Identifying' names are the ones that should should be avoided in favour of id.
什么是“命名元素”?任何带有id, 以及name用于“识别”目的的任何东西:即表单、图像、锚点和其他一些name属性,但不是其他不相关的属性实例,例如表单输入字段中的控件名称、中的参数名称<param>或元数据类型<meta>. '识别' names 是应该避免的那些id。
回答by TJ VanToll
As mentioned in the earlier answer this behavior is known as named access on the window object.  The value of the nameattribute for some elements and the value of the idattribute for all elements are made available as properties of the global windowobject.  These are known as named elements.  Since windowis the global object in the browser, each named element will be accessible as a global variable.
正如前面的回答中提到的,这种行为被称为对 window 对象的命名访问。该值name的某些元素属性和值id的所有元素的属性都可用作为全球性质window的对象。这些被称为命名元素。由于window是浏览器中的全局对象,因此每个命名元素都可以作为全局变量访问。
This was originally added by Internet Explorer and eventually was implemented by all other browsers simply for compatibility with sites that are dependent on this behavior. Interestingly, Gecko (Firefox's rendering engine) chose to implement this in quirks modeonly, whereas other rendering engines left it on in standards mode.
这最初是由 Internet Explorer 添加的,最终由所有其他浏览器实现,只是为了与依赖此行为的站点兼容。有趣的是,Gecko(Firefox 的渲染引擎)选择仅在quirks 模式下实现此功能,而其他渲染引擎则将其保留在标准模式下。
However, as of Firefox 14, Firefox  now supports named accesson the windowobject in standards mode as well.  Why did they change this?  Turns out there's still a lot of sites that rely on this functionality in standards mode.  Microsoft even released a marketing demothat did, preventing the demo from working in Firefox.
但是,从 Firefox 14 开始,Firefox 现在也支持window在标准模式下对对象进行命名访问。他们为什么要改变这一点?事实证明,仍然有很多站点在标准模式下依赖此功能。微软甚至发布了一个营销演示,阻止了该演示在 Firefox 中工作。
Webkit has recently considered the opposite, relegating named access on the windowobject to quirks mode only.  They decided against it by the same reasoning as Gecko.
Webkit 最近考虑了相反的情况,将window对象上的命名访问仅降级为quirks 模式。他们根据与 Gecko 相同的推理决定反对它。
So… crazy as it seems this behavior is now technically safe to use in the latest version of all major browsers in standards mode. But while named access can seem somewhat convenient , it should not be used.
所以......疯狂,因为现在这种行为在标准模式下在所有主要浏览器的最新版本中使用在技术上是安全的。但是,虽然命名访问看起来有些方便,但不应该使用它。
Why?  A lot of the reasoning can be summed up in this article about why global variables are bad.  Simply put, having a bunch of extra global variables leads to more bugs.  Let's say you accidentally type the name of a varand happen to type an idof a DOM node, SURPRISE!
为什么?这篇文章中可以总结出很多关于全局变量为什么不好的推理。简单地说,拥有一堆额外的全局变量会导致更多的错误。假设您不小心键入了 a 的名称,但var碰巧键入id了 DOM 节点的an ,这让您大吃一惊!
Additionally, despite being standardized there are still quite a few discrepancies in browser's implementations of named access.
此外,尽管已经标准化,但浏览器的命名访问实现仍然存在相当多的差异。
- IE incorrectly makes the value of the 
nameattribute accessible for form elements (input, select, etc). - Gecko and Webkit incorrectly do NOT make 
<a>tags accessible via theirnameattribute. - Gecko incorrectly handles multiple named elements with the same name (it returns a reference to a single node instead of an array of references).
 
- IE 错误地使
name属性值可用于表单元素(输入、选择等)。 - Gecko 和 Webkit 错误地不会
<a>通过其name属性访问标签。 - Gecko 错误地处理多个具有相同名称的命名元素(它返回对单个节点的引用而不是引用数组)。
 
And I'm sure there's more if you try using named access on edge cases.
如果您尝试在边缘情况下使用命名访问,我相信还有更多。
As mentioned in other answers use document.getElementByIdto get a reference to a DOM node by its id.  If you need to get a reference to a node by its nameattribute use document.querySelectorAll.
正如其他答案中提到的,用于document.getElementById通过id. 如果您需要通过其name属性获取对节点的引用,请使用document.querySelectorAll.
Please, please do not propagate this problem by using named access in your site. So many web developers have wasted time trying to track down this magicalbehavior. We really need to take action and get rendering engines to turn named access off in standards mode. In the short term it will break some sites doing bad things, but in the long run it'll help move the web forward.
请不要通过在您的站点中使用命名访问来传播此问题。许多 Web 开发人员都在浪费时间试图追踪这种神奇的行为。我们真的需要采取行动并让渲染引擎在标准模式下关闭命名访问。在短期内,它会破坏一些做坏事的网站,但从长远来看,它将有助于推动网络向前发展。
If you're interested I talk about this in more detail on my blog - https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/.
如果您有兴趣,我会在我的博客上更详细地讨论这个问题 - https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/。
回答by Nick Craver
You should stick to getElementById()in these cases, for example:
getElementById()在这些情况下,您应该坚持,例如:
document.getElementById('example').innerHTML
IE likes to mix elements with nameandIDattributes in the global namespace, so best to be explicit about what you're trying to get.
IE 喜欢在全局命名空间中混合元素name和ID属性,因此最好明确说明您想要获得的内容。
回答by qff
Yes, they do.
是的,他们这样做。
Tested in Chrome 55, Firefox 50, IE 11, IE Edge 14, and Safari 10
with the following example: 
使用以下示例在 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>
回答by Bekim Bacaj
The question should sound:: "Do HTML Tags with provided IDs become globally accessible DOM Elements?"
问题应该是:“带有提供 ID 的 HTML 标签是否会成为全局可访问的 DOM 元素?”
The answer is YES!
答案是肯定的!
That's how it was meant to work, and that's why IDs were introduced by W3C to begin with.: The ID of an HTML Tag in a parsed scripting environment becomes its corresponding DOM Element handle.
这就是它的工作原理,这就是 W3C 开始引入 ID 的原因。: 解析脚本环境中的 HTML 标记的 ID 成为其对应的 DOM 元素句柄。
However, Netscape Mozilla refused to conform to (to them intruding) W3C and stubbornly kept using the deprecated Name attribute to create havoc and therefore break the Scripting functionality and the coding convenience brought in by the W3C's introduction of Unique IDs.
然而,Netscape Mozilla 拒绝遵守(对他们来说是侵入性的)W3C 并顽固地继续使用已弃用的 Name 属性来制造破坏,因此破坏了 W3C 引入唯一 ID 带来的脚本功能和编码便利。
After the Netscape Navigator 4.7 fiasco their developers all went and infiltrated the W3C, whereas their associates were superseding the Web with wrong practices and misusing examples. Forcing the use and reuse of already deprecated Name attribute [!which was not meant to be unique] on par with ID attributes so that scripts that utilized ID handles for accessing particular DOM elements would simply break!
在 Netscape Navigator 4.7 惨败之后,他们的开发人员都去渗透了 W3C,而他们的同事正在以错误的做法和滥用示例取代 Web。强制使用和重用已弃用的 Name 属性 [! 这并不意味着是唯一的] 与 ID 属性相同,这样使用 ID 句柄访问特定 DOM 元素的脚本就会崩溃!
And break they did as they would also write and publish extensive coding lessons and examples [their browser would not recognize anyway] such as  document.all.ElementID.propertyinstead of ElementID.propertyto at least make it inefficient and give the browser more overhead in case it didn't simply break it at HTML domain by using the same token for the (now [1996-97], deprecated) Name and the standard ID attribute supplying it with the same token value.
并打破他们做了,因为他们也撰写和发表大量的编码的经验教训和例子[他们的浏览器将不会反正承认]例如  document.all.ElementID.property,而不是ElementID.property至少使其效率低下,更多的开销给浏览器的情况下,它没有简单地打破它HTML 域使用相同的标记(现在 [1996-97],已弃用)名称和标准 ID 属性为其提供相同的标记值。
They easily managed to convince the - back then - overwhelming army of ignorant code-writing amateurs that Names and IDs are practically the same, except that ID attribute is shorter and therefore byte-saving and more convenient to the coder than the ancient Name property. Which was of course a lie. Or - in their superseding published articles of HTML, convincing articles that you'll need to provide both Name and ID to your tags for them to be accessible by the Scripting engine.
他们很容易地说服了当时压倒性的无知的代码编写爱好者大军,Names 和 ID 实际上是相同的,除了 ID 属性更短,因此比古老的 Name 属性更节省字节并且对编码人员更方便。这当然是谎言。或者 - 在他们取代已发布的 HTML 文章中,说服文章您需要为标签提供名称和 ID,以便脚本引擎可以访问它们。
Mosaic Killers [codenamed "Mozilla"] were so pissed they thought "if we go down, so should Internet".
Mosaic Killers [代号为“Mozilla”] 非常生气,他们认为“如果我们失败了,互联网也应该如此”。
The rising Microsoft - on the other hand - were so naive they thought they should keep the deprecated and marked for deletion Name property and treat it as if it was an ID that is a unique Identifier so that they wouldn't break the scripting functionality of old pages coded by Netscape trainees. They were deadly wrong...
另一方面,崛起的微软太天真了,他们认为他们应该保留已弃用并标记为删除的 Name 属性,并将其视为唯一标识符的 ID,这样他们就不会破坏脚本功能Netscape 受训人员编码的旧页面。他们大错特错……
And the returning of an array collection of ID conflicting elements was not a solution to this deliberate man-made problem either. Actually it defeated the whole purpose.
并且返回 ID 冲突元素的数组集合也不是解决这个故意人为问题的方法。事实上,它违背了整个目的。
And this is the sole reason W3C turned ugly and gave us idiocies such as document.getElementByIdand the accompanying rococo goddamn annoying syntax of the sort...
 (...)
这就是 W3C 变得丑陋并给我们带来诸如document.getElementById洛可可式这种令人讨厌的洛可可式语法之类的白痴的唯一原因......(......)

