为什么我们不在JavaScript中使用元素ID作为标识符?

问题描述 投票:48回答:4

我开始使用的所有浏览器都允许通过简单编写来访问id="myDiv"元素:

myDiv

见这里:http://jsfiddle.net/L91q54Lt/

无论如何,这种方法似乎记录很少,事实上,我遇到的来源甚至没有提及,而是假设有人会使用

document.getElementById("myDiv")

或者可能

document.querySelector("#myDiv")

即使在事先知道其ID(即未在运行时计算)时也访问DOM元素。我可以说,如果有人无意中试图在更广泛的范围内重新定义myDiv,那么后一种方法具有保持代码安全的优点(虽然不是这么好的想法......),用一些不同的值覆盖它并继续而没有注意到冲突。

但其他那个呢?除了代码设计之外,使用上面的简短形式是否有任何问题,或者我在这里缺少什么?

javascript dom getelementbyid
4个回答
42
投票

无论如何,这种方法似乎记录很差,事实上,我遇到的消息来源甚至没有提及[...]

除了隐含声明的全局变量之外,缺乏文档是不使用它的一个重要原因。

id值明显提升为全局变量并不符合标准(HTML5 spec for the ID attribute没有提及它),因此,您不应该假设未来的浏览器会实现它。

编辑:事实证明这种行为符合标准 - 在HTML5中,window应支持对“命名元素”的属性访问:

出于上述算法的目的,具有名称名称的命名对象是以下任一种:

  • 子浏览名称为name的活动文档的上下文
  • a,applet,area,embed,form,frameset,img或具有名称内容属性,其值为name的对象元素,或者
  • 具有id内容属性,其值为name的HTML元素。

资料来源:HTML 5 spec, 'Named access on window object",强调我的。

基于此,标准合规性不是避免这种模式的理由。但是,规范本身建议不要使用它:

作为一般规则,依赖于此将导致脆弱的代码。例如,随着新功能添加到Web平台,哪些ID最终映射到此API可能会随着时间的推移而变化。而不是这个,使用document.getElementById()document.querySelector()


20
投票

好问题。正如爱因斯坦可能没有说的那样,事情应尽可能简单,并不简单。

如果有人无意中尝试在更广泛的范围内重新定义myDiv(虽然不是这么好的想法......),后一种方法的优点是保持代码安全,用一些不同的值覆盖它并继续而不注意冲突

这就是为什么这是一个坏主意的主要原因,而且这已经足够了。全局变量不能安全依赖。它们可以随时被任何最终在页面上运行的脚本覆盖。

除此之外,只需输入myDiv就不是document.getElementById()的“简短形式”。它是对全局变量的引用。如果元素不存在,document.getElementById()将很乐意返回null,而尝试访问不存在的全局变量将引发引用错误,因此您需要将引用包装到全局变量中。一个try / catch块是安全的。

这就是为什么jQuery如此受欢迎的一个原因:如果你做$("#myDiv").remove(),并且没有id为myDiv的元素,则不会抛出任何错误 - 代码将默默无所事事,这通常正是你在做DOM时所需要的操纵。


12
投票

有几个原因:

您不希望您的代码和标记耦合在一起。

通过使用特定的调用来访问div,您不必担心全局空间被破坏。添加一个在全球空间中声明myDiv的库,您将陷入一个难以修复的痛苦世界。

您可以按ID访问不属于DOM的元素

它们可以位于片段,框架或已分离但尚未重新附加到DOM的元素中。

编辑:ID访问非附加元素的示例

var frag = document.createDocumentFragment();
var span = document.createElement("span");
span.id = "span-test";
frag.appendChild(span);
var span2 = frag.getElementById("span-test");
alert(span === span2);

2
投票

在我的情况下,我的页面中有一个iframe。我对id属性vs name属性感到困惑,这两个属性都影响了一个名为inner_iframe的变量,可以从window访问!

  • 如果我只使用id属性,如id="inner_iframe"window.inner_iframeHTMLIFrameElement。属性包括inner_iframe.contentDocumentinner_iframe.contentWindow as described here * 在这种情况下,我假设变量出现在window上,因为quoted by @joew in the accepted answer: 具有id内容属性,其值为name的HTML元素
  • 如果我只使用name属性,比如name="inner_iframe",那么window.inner_iframe就是一个“框架”,又名"window object"contentWindow,因此名称属性inner_iframe没有属性contentDocumentcontentWindow。 我假设inner_iframe变量出现在window,因为quoted by @joew in the accepted answer的原因 子浏览名称为name的活动文档的上下文
  • 如果我同时使用了nameid属性,并且我给了两个属性相同的值name="inner_iframe" id="inner-iframe"; name属性trumped / clobbered the id属性;我被留下了“窗口对象”,而不是HTMLIFrameElement

所以我的观点是要小心模棱两可; nameid之间的冲突属于同一个具有两个不同API的对象:只是一个特定的情况,其中隐式行为和对窗口变量的附加可能会让您感到困惑。

*(并且只有当<script>在HTML中的<iframe>之后/之下加载,或者<script>在尝试通过id属性访问之前等到window.onload

**此“框架”与DOM元素的区别在Mozilla文档中描述为:

window.frames伪数组中的每个项表示与给定的内容相对应的窗口对象,而不是(i)帧DOM元素(即,window.frames [0]与document.getElementsByTagName相同。 ( “IFRAME”)[0] .contentWindow)。

© www.soinside.com 2019 - 2024. All rights reserved.