具有 ID 的 DOM 树元素会成为全局属性吗?

发布于 2024-09-13 12:37:01 字数 926 浏览 6 评论 0原文

在研究简单 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

〗斷ホ乔殘χμё〖 2024-09-20 12:37:01

应该发生的情况是“命名元素”被添加为 document 对象的明显属性。这是一个非常糟糕的主意,因为它允许元素名称与 document 的实际属性发生冲突。

IE 还添加命名元素作为 window 对象的属性,从而使情况变得更糟。这是双重糟糕的,因为现在您必须避免在您的 documentwindow 对象(或项目中的任何其他库代码)的任何成员之后命名您的元素可能想用。

这也意味着这些元素作为类似全局的变量是可见的。幸运的是,在这种情况下,代码中的任何真正的全局 varfunction 声明都会隐藏它们,因此您无需太担心此处的命名,但如果您尝试如果对名称冲突的全局变量进行赋值,并且忘记声明它 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 of document.

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 the document or the window 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 or function 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 it var, 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 on window or 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 getElementById call to use a quick lookup anyway; all you get is problems when elements change id 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 on window 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 a name being used for ‘identifying’ purposes: that is, forms, images, anchors and a few others, but not other unrelated instances of a name attribute, like control-names in form input fields, parameter names in <param> or metadata type in <meta>. ‘Identifying’ names are the ones that should be avoided in favour of id.

︶葆Ⅱㄣ 2024-09-20 12:37:01

正如前面的答案中提到的,这种行为被称为 对窗口对象的命名访问。某些元素的 name 属性值和所有元素的 id 属性值可用作全局 window 对象的属性。这些被称为命名元素。由于window是浏览器中的全局对象,因此每个命名元素都可以作为全局变量进行访问。

它最初是由 Internet Explorer 添加的,最终由所有其他浏览器实现,只是为了与依赖于此行为的网站兼容。有趣的是,Gecko(Firefox 的渲染引擎)选择仅在 怪异模式 中实现此功能,而其他渲染引擎将其保留在标准模式下。

不过,从 Firefox 14 开始,Firefox 现在支持 上的命名访问标准模式下的 window 对象也是如此。他们为什么要改变这个?事实证明,仍然有很多网站在标准模式下依赖此功能。微软甚至发布了一个营销演示,但该演示无法在 Firefox 中运行。

Webkit 最近考虑了相反的,将 < code>window 对象仅适用于怪异模式。他们以与 Gecko 相同的理由决定反对它。

所以......疯狂的是,这种行为现在技术上可以安全地在标准模式下的所有主要浏览器的最新版本中使用。但是,虽然命名访问看起来有些方便,但不应该使用它

为什么?本文可以总结关于为什么全局变量不好的很多推理。简而言之,拥有一堆额外的全局变量会导致更多错误。假设您不小心输入了 var 的名称,并且碰巧输入了 DOM 节点的 id,令人惊讶!

此外,尽管已经标准化,但浏览器的命名访问实现仍然存在相当多的差异。

  • IE 错误地使 name 属性的值可供表单元素(输入、选择等)访问。
  • Gecko 和 Webkit 错误地不使 标记通过其 name 属性进行访问。
  • Gecko 错误地处理具有相同名称的多个命名元素(它返回对单个节点的引用而不是引用数组)。

而且我确信如果您尝试在边缘情况下使用命名访问,还会有更多。

正如其他答案中提到的,使用 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 the id attribute for all elements are made available as properties of the global window object. These are known as named elements. Since window 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 an id of a DOM node, SURPRISE!

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 name attribute accessible for form elements (input, select, etc).
  • Gecko and Webkit incorrectly do NOT make <a> tags accessible via their name attribute.
  • Gecko incorrectly handles multiple named elements with the same name (it returns a reference to a single node instead of an array of references).

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 its id. If you need to get a reference to a node by its name attribute use 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 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/.

吝吻 2024-09-20 12:37:01

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

document.getElementById('example').innerHTML

IE 喜欢将元素与 name ID 全局命名空间中的属性,因此最好明确您想要获取的内容。

You should stick to getElementById() in these cases, for example:

document.getElementById('example').innerHTML

IE likes to mix elements with name and ID attributes in the global namespace, so best to be explicit about what you're trying to get.

旧时光的容颜 2024-09-20 12:37:01

问题应该是:“具有提供的 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 of ElementID.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...
(...)

将军与妓 2024-09-20 12:37:01

是的。

已在 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

Yes, they do.

Tested in Chrome 55, Firefox 50, IE 11, IE Edge 14, and Safari 10
with the following example:

<!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

丘比特射中我 2024-09-20 12:37:01

document.all 需要取消弃用并进行一些修复

具有 idname 的元素可用在 document.all 中,这对我来说是一个令人兴奋的消息。

然而,据我所知,all 已被老前辈弃用和吐槽,但似乎没有人能够提供任何令人信服的理由从不使用它,或者至少提供足够有力的论据为什么它应该被弃用。

我将它用于一个小的内部工具页面,它完全可以工作......现在。它确实有问题,但便利性和清洁度也不容忽视:

Given

<h1 id="welcomeMessage" hidden>Welcome!</h1>

You can do

document.all.welcomeMessage.hidden = false

vs.

document.getElementById('welcomeMessage').hidden = false
document.querySelector('#welcomeMessage').hidden = false

So Nice!但存在一些问题:

  • 如果碰巧有多个元素具有相同的 id (有可能,但可以而且应该避免)或 name (非常有可能并且可以)不能避免,因为复选框组),然后返回一个 HTMLCollection,而不是单个 Element
  • 如果您出于某种原因尝试获取具有匹配的 id 或名称的元素继承的属性如 __proto__toString,那么你将得到这些对象而不是 undefined
  • 它不如 document.getElementById< /code>,所以如果您查询大量元素,就会存在性能问题

一个不错的替代方案

我决定这样做,我不太确定我参加聚会有多晚,但我'我喜欢这个:

const elements = new Proxy({}, {
  get(target, prop) {
    return document.getElementById(prop) || document.getElementsByName(prop)[0];
  }
});

// Clean and direct access to elements just like document.all
elements.welcomeMessage.hidden = false

document.all needs to be un-deprecated and fixed up a bit

Elements with an id or name are available in document.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

<h1 id="welcomeMessage" hidden>Welcome!</h1>

You can do

document.all.welcomeMessage.hidden = false

vs.

document.getElementById('welcomeMessage').hidden = false
document.querySelector('#welcomeMessage').hidden = false

So nice! But there's some problems:

  • If there happens to be more than one element with the same id (possible, but can and should be avoided) or name (very possible and can't be avoided because of checkbox groups), then an HTMLCollection is returned, not a single Element
  • If you for some reason try to get an element with an id or name that matches inherited properties like __proto__ or toString, then you'll get those objects instead of undefined
  • It's not as fast as document.getElementById, so there's performance concerns if you're querying tons of elements

A 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:

const elements = new Proxy({}, {
  get(target, prop) {
    return document.getElementById(prop) || document.getElementsByName(prop)[0];
  }
});

// Clean and direct access to elements just like document.all
elements.welcomeMessage.hidden = false

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文