具有 ID 的 DOM 树元素会成为全局属性吗?
在研究简单 HTMLElement
包装器的想法时,我偶然发现了 Internet Explorer 和 Chrome:
对于 DOM 树中具有 id
的给定 HTMLElement
,可以检索
使用其 ID 作为变量名或作为 window
的属性。
<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 方法?
Working on an idea for a simple HTMLElement
wrapper I stumbled upon the following for Internet Explorer and Chrome:
For a given HTMLElement
with an id
in the DOM tree, it is possible to retrieve the <div>
using its ID as a variable name or as a property of window
. So for a <div>
like
<div id="example">some text</div>
in Internet Explorer 8 and Chrome you can do:
alert(example.innerHTML); // Alerts "some text".
or
alert(window["example"].innerHTML); // Alerts "some text".
So, does this mean every element in the DOM tree is converted to a property on the global object? And does it also mean one can use this as a replacement for the getElementById
method in these browsers?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
应该发生的情况是“命名元素”被添加为
document
对象的明显属性。这是一个非常糟糕的主意,因为它允许元素名称与document
的实际属性发生冲突。IE 还添加命名元素作为
window
对象的属性,从而使情况变得更糟。这是双重糟糕的,因为现在您必须避免在您的document
或window
对象(或项目中的任何其他库代码)的任何成员之后命名您的元素可能想用。这也意味着这些元素作为类似全局的变量是可见的。幸运的是,在这种情况下,代码中的任何真正的全局
var
或function
声明都会隐藏它们,因此您无需太担心此处的命名,但如果您尝试如果对名称冲突的全局变量进行赋值,并且忘记声明它var
,那么当 IE 尝试将值赋给元素本身时,您会在 IE 中收到错误消息。通常认为省略
var
以及依赖在window
上可见或作为全局变量的命名元素是不好的做法。坚持使用document.getElementById
,它得到更广泛的支持并且更明确。如果您不喜欢打字,您可以编写一个名称较短的简单包装函数。无论哪种方式,使用 id 到元素查找缓存都是没有意义的,因为浏览器通常会优化getElementById
调用以无论如何使用快速查找;当元素更改id
或在文档中添加/删除元素时,您遇到的只是问题。Opera 复制了 IE,然后 WebKit 加入进来,现在既包括以前将命名元素放在
document
属性上的非标准化做法,也包括以前仅适用于 IE 的将它们放在window
上的做法。 code> 是 正在 由 HTML5 标准化,其方法是记录和标准化每个浏览器作者给我们带来了可怕的做法,使它们永远成为网络的一部分。所以Firefox 4也将支持这一点。什么是“命名元素”?任何带有
id
的内容,以及带有name
的任何内容,用于“识别”目的:即表单、图像、锚点和其他一些内容,但不包括其他不相关的实例name
属性的名称,例如表单输入字段中的控件名称、中的参数名称或
中的元数据类型。应避免使用“识别”
name
,而使用id
。What is supposed to happen is that ‘named elements’ are added as apparent properties of the
document
object. This is a really bad idea, as it allows element names to clash with real properties ofdocument
.IE made the situation worse by also adding named elements as properties of the
window
object. This is doubly bad in that now you have to avoid naming your elements after any member of either thedocument
or thewindow
object you (or any other library code in your project) might want to use.It also means that these elements are visible as global-like variables. Luckily in this case any real global
var
orfunction
declarations 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 itvar
, you'll get an error in IE as it tries to assign the value to the element itself.It's generally considered bad practice to omit
var
, as well as to rely on named elements being visible onwindow
or as globals. Stick todocument.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 thegetElementById
call to use a quick lookup anyway; all you get is problems when elements changeid
or are added/removed from the document.Opera copied IE, then WebKit joined in, and now both the previously-unstandardised practice of putting named elements on
document
properties, and the previously-IE-only practice of putting them onwindow
are being standardised by 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.What are ‘named elements’? Anything with an
id
, and anything with aname
being used for ‘identifying’ purposes: that is, forms, images, anchors and a few others, but not other unrelated instances of aname
attribute, like control-names in form input fields, parameter names in<param>
or metadata type in<meta>
. ‘Identifying’name
s are the ones that should be avoided in favour ofid
.正如前面的答案中提到的,这种行为被称为 对窗口对象的命名访问。某些元素的
name
属性值和所有元素的id
属性值可用作全局window
对象的属性。这些被称为命名元素。由于window
是浏览器中的全局对象,因此每个命名元素都可以作为全局变量进行访问。它最初是由 Internet Explorer 添加的,最终由所有其他浏览器实现,只是为了与依赖于此行为的网站兼容。有趣的是,Gecko(Firefox 的渲染引擎)选择仅在 怪异模式 中实现此功能,而其他渲染引擎将其保留在标准模式下。
不过,从 Firefox 14 开始,Firefox 现在支持
上的命名访问
标准模式下的 window
对象也是如此。他们为什么要改变这个?事实证明,仍然有很多网站在标准模式下依赖此功能。微软甚至发布了一个营销演示,但该演示无法在 Firefox 中运行。Webkit 最近考虑了相反的,将 < code>window 对象仅适用于怪异模式。他们以与 Gecko 相同的理由决定反对它。
所以......疯狂的是,这种行为现在技术上可以安全地在标准模式下的所有主要浏览器的最新版本中使用。但是,虽然命名访问看起来有些方便,但不应该使用它。
为什么?本文可以总结关于为什么全局变量不好的很多推理。简而言之,拥有一堆额外的全局变量会导致更多错误。假设您不小心输入了
var
的名称,并且碰巧输入了 DOM 节点的id
,令人惊讶!此外,尽管已经标准化,但浏览器的命名访问实现仍然存在相当多的差异。
name
属性的值可供表单元素(输入、选择等)访问。标记通过其
name
属性进行访问。而且我确信如果您尝试在边缘情况下使用命名访问,还会有更多。
正如其他答案中提到的,使用
document.getElementById
通过其id
获取对 DOM 节点的引用。如果您需要通过节点的name
属性获取对节点的引用,请使用document.querySelectorAll
。请不要通过在您的站点中使用命名访问来传播此问题。许多网络开发人员都浪费时间试图追踪这种神奇的行为。我们确实需要采取行动并让渲染引擎在标准模式下关闭命名访问。从短期来看,它会破坏一些做坏事的网站,但从长远来看,它将有助于推动网络向前发展。
如果您有兴趣,我会在我的博客上更详细地讨论这一点 - https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/。
As mentioned in the earlier answer this behavior is known as named access on the window object. The value of the
name
attribute for some elements and the value of theid
attribute for all elements are made available as properties of the globalwindow
object. These are known as named elements. Sincewindow
is the global object in the browser, each named element will be accessible as a global variable.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 mode only, whereas other rendering engines left it on in standards mode.
However, as of Firefox 14, Firefox now supports named access on the
window
object 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 demo that did, preventing the demo from working in Firefox.Webkit has recently considered the opposite, relegating named access on the
window
object to quirks mode only. They decided against it by the same reasoning as 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
var
and happen to type anid
of a DOM node, SURPRISE!Additionally, despite being standardized there are still quite a few discrepancies in browser's implementations of named access.
name
attribute accessible for form elements (input, select, etc).<a>
tags accessible via theirname
attribute.And I'm sure there's more if you try using named access on edge cases.
As mentioned in other answers use
document.getElementById
to get a reference to a DOM node by itsid
. If you need to get a reference to a node by itsname
attribute usedocument.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 magical behavior. 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.
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/.
在这些情况下,您应该坚持使用
getElementById()
,例如:IE 喜欢将元素与
name
和ID
全局命名空间中的属性,因此最好明确您想要获取的内容。You should stick to
getElementById()
in these cases, for example:IE likes to mix elements with
name
andID
attributes in the global namespace, so best to be explicit about what you're trying to get.问题应该是:“具有提供的 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 属性来破坏它它具有相同的令牌值。
他们轻松地说服了——当时——压倒性的无知代码编写业余爱好者大军,名称和 ID 实际上是相同的,只是 ID 属性更短,因此比古老的 Name 属性更节省字节,对编码人员来说更方便。这当然是谎言。或者 - 在他们发布的替代 HTML 文章中,令人信服的文章表明您需要为标记提供名称和 ID,以便脚本引擎可以访问它们。
马赛克杀手(代号“Mozilla”)非常生气,他们认为“如果我们倒闭,互联网也应该倒闭”。
另一方面,崛起的微软非常天真,他们认为应该保留已弃用并标记为删除的 Name 属性,并将其视为唯一标识符的 ID,这样他们就不会破坏由 Netscape 实习生编码的旧页面。他们大错特错了……
返回 ID 冲突元素的数组集合也不能解决这个故意的人为问题。事实上它违背了整个目的。
这就是 W3C 变得丑陋并给我们带来诸如
document.getElementById
之类的白痴以及伴随的洛可可式令人讨厌的语法的唯一原因......(...)
The question should sound:: "Do HTML Tags with provided IDs become globally accessible DOM Elements?"
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.
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.
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!
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.property
instead ofElementID.property
to 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.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.
Mosaic Killers [codenamed "Mozilla"] were so pissed they thought "if we go down, so should Internet".
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...
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.
And this is the sole reason W3C turned ugly and gave us idiocies such as
document.getElementById
and the accompanying rococo goddamn annoying syntax of the sort...(...)
是的。
已在 Chrome 55、Firefox 50、IE 11、IE Edge 14 和 Safari 10 中进行测试
使用以下示例:
http://jsbin.com/mahobinopa/edit?html,output
Yes, they do.
Tested in Chrome 55, Firefox 50, IE 11, IE Edge 14, and Safari 10
with the following example:
http://jsbin.com/mahobinopa/edit?html,output
document.all
需要取消弃用并进行一些修复具有
id
或name
的元素可用在document.all
中,这对我来说是一个令人兴奋的消息。然而,据我所知,
all
已被老前辈弃用和吐槽,但似乎没有人能够提供任何令人信服的理由从不使用它,或者至少提供足够有力的论据为什么它应该被弃用。我将它用于一个小的内部工具页面,它完全可以工作......现在。它确实有问题,但便利性和清洁度也不容忽视:
Given
You can do
vs.
So Nice!但存在一些问题:
id
(有可能,但可以而且应该避免)或name
(非常有可能并且可以)不能避免,因为复选框组),然后返回一个HTMLCollection
,而不是单个Element
__proto__
或toString
,那么你将得到这些对象而不是undefined
document.getElementById< /code>,所以如果您查询大量元素,就会存在性能问题
一个不错的替代方案
我决定这样做,我不太确定我参加聚会有多晚,但我'我喜欢这个:
document.all
needs to be un-deprecated and fixed up a bitElements with an
id
orname
are available indocument.all
, which was exciting news to me.However, from what I've gathered
all
is deprecated and spit upon by old-timers, BUT no one seems to be able to provide any compelling reason to never use it, or at least a strong enough argument for why it should be deprecated.I'm using it for a little internal tool page and it totally works...for now. It does have problems, but the convenience and cleanliness can't be ignored:
Given
You can do
vs.
So nice! But there's some problems:
id
(possible, but can and should be avoided) orname
(very possible and can't be avoided because of checkbox groups), then anHTMLCollection
is returned, not a singleElement
__proto__
ortoString
, then you'll get those objects instead ofundefined
document.getElementById
, so there's performance concerns if you're querying tons of elementsA nice alternative
I decided to do this instead and I'm not really sure how late I am to the party, but I'm lovin' this: