为什么不在JavaScript中直接使用元素id作为标识符呢?
Why don't we just use element IDs as identifiers in JavaScript?
我使用过的所有浏览器都允许使用id="myDiv"
访问元素,只需输入:
myDiv
请看这里:http://jsfiddle.net/L91q54Lt/
无论如何,这个方法的文档似乎很差,事实上,我遇到的资料甚至没有提到它,而是假设人们会使用
document.getElementById("myDiv")
或者
document.querySelector("#myDiv")
来访问一个DOM元素,即使它的ID是事先已知的(即在运行时不计算)。我可以告诉你,如果有人无意中试图在更广泛的范围内重新定义myDiv
(虽然不是一个聪明的想法……),用一些不同的值覆盖它,并且在没有注意到冲突的情况下继续进行,后一种方法具有保持代码安全的优势。
但是除此之外呢?除了代码设计之外,使用上面的简短形式还有什么问题吗?或者我在这里还遗漏了什么?
除了依赖隐式声明的全局变量之外,缺乏文档是不使用它的一个重要原因。无论如何,这个方法的文档似乎很差,事实上,我遇到的来源甚至没有提到它[…]
将id
值提升为全局变量是不符合标准的(HTML5规范中没有提到ID属性),因此,你不应该假设未来的浏览器会实现它。
window
应该支持对"命名元素"的属性访问:
对于上述算法而言,带有name的命名对象是:
- 活动文档的子浏览上下文,其名称为name,
- a、applet、area、embed、form、framset、img或object元素name内容属性,其值为name或
- HTML元素的id content属性值为name。
来源:HTML 5规范,"命名访问窗口对象",强调mine。
基于此,遵循标准不是避免此模式的理由。然而,规范本身不建议使用它:
作为一般规则,依赖于此将导致脆弱的代码。哪一个映射到此API的id可能随着时间的推移而变化,就像新特性一样添加到Web平台,例如。而不是这个,使用
document.getElementById()
或document.querySelector()
.
问得好。正如爱因斯坦可能没有说过的那样,事情应该尽可能简单,而不是更简单。
后一种方法的优点是,如果有人无意中试图在更广泛的范围内重新定义myDiv(虽然不是一个好主意……),用一些不同的值覆盖它,然后继续使用,而不注意冲突
这就是为什么这是一个坏主意的主要原因,而且这已经足够了。依赖全局变量是不安全的。它们可以在任何时候被最终在页面上运行的任何脚本覆盖。
除此之外,仅仅输入myDiv
并不是document.getElementById()
的"缩写形式"。它是对全局变量的引用。如果元素不存在,document.getElementById()
将愉快地返回null
,而试图访问不存在的全局变量将抛出引用错误,因此您需要将对全局变量的引用包装在try/catch块中以确保安全。
这是jQuery如此受欢迎的一个原因:如果您执行$("#myDiv").remove()
,并且没有id为myDiv
的元素,则不会抛出错误—代码将静默地不做任何事情,这通常正是您在进行DOM操作时想要的。
原因如下:
你不希望你的代码和你的标记耦合。
通过使用特定的调用来访问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);
在我的例子中,我的页面中有一个iframe。我对id
属性和name
属性感到困惑,这两个属性都影响了一个名为inner_iframe
的变量,可以从window
访问!
-
如果我只使用id属性,像
id="inner_iframe"
一样,window.inner_iframe
是HTMLIFrameElement
。属性包括inner_iframe.contentDocument
和inner_iframe.contentWindow
,如下所述*- 在这种情况下,我假设变量出现在
window
上,因为在可接受的答案中@joew引用的原因:具有id content属性且值为name的 HTML元素
- 在这种情况下,我假设变量出现在
-
如果我只使用名称属性,像
name="inner_iframe"
那么window.inner_iframe
是一个"框架",又名"窗口对象"。不具有contentDocument
或contentWindow
属性。- 我假设
inner_iframe
变量出现在window
上,因为@joew在可接受的答案中引用了原因name为name 的活动文档的子浏览上下文
- 我假设
- 如果我使用
name
和id
属性,我给这两个属性相同的值name="inner_iframe" id="inner-iframe"
;name
属性胜过/击败了id
属性;我留下了"窗口对象",而不是HTMLIFrameElement
!
所以我的观点是要小心歧义;name
和id
属性之间的冲突,在同一个对象与两个不同的api:只是一个特定的情况下,隐式行为和附加到一个窗口变量可能会混淆你。
*(仅当<script>
加载在HTML中的<iframe>
之后/之下,或者<script>
在尝试通过id属性访问window.onload
之前等待CC_43)
**这个"框架"和DOM元素的区别在Mozilla文档中描述为:
window.frames伪数组中的每一项都代表了对应于给定's或's内容的窗口对象,而不是(i)frame DOM元素(即window.frames[0]与document.getElementsByTagName("iframe")[0]. contentwindow)。
作为一个开发基于web的应用程序超过25年的人,我可以肯定地说,这种奇怪行为的唯一原因是向后兼容性。
方法getElementById
甚至不是DOM Level 1的一部分。但是,早期的DOM Level 0允许直接访问页面上的大多数元素:
正如你所看到的,像Netscape 6和MSIE 5这样的浏览器继续支持旧的约定,甚至在getElementById
被采纳为"标准"之后。
为了向后兼容,甚至是更高级的浏览器那些支持1级DOM的人,仍然支持旧的,忠实的0级DOM。不支持它意味着最普通脚本突然不再工作了。所以即使0级DOM并不完全适合新的DOM概念,即浏览器将继续支持。
当Netscape引入0级DOM时,人们可能认为基于web的应用程序永远不会超过自动填充几个表单字段和在屏幕上移动一些图像。因此,不用担心使用少量元素id污染全局窗口对象。
显然,这个解决方案根本不能很好地扩展。但是为了不破坏遗留的Javascript代码,我们仍然坚持使用这个古老的0级DOM约定。
- 如何将HTML id分配给元素,以及如何将JavaScript应用于元素
- difference between '$(<%= DDL.ID %>) & $('
- 使用Javascript获取所选选项ID
- 根据id将json数组组合为一个json数组
- 是否有一个JS/jQuery函数可以获取某个类的每个元素的ID
- Javascript未捕获语法错误意外的标识符错误
- 对id以某个字符串开头的元素进行计数
- 如果元素's的ID以数字开头
- 通过id和class属性获取元素
- 根据选项卡内部的文本链接中的哈希ID动态选择jqueryUI选项卡
- 使用当前日期生成随机id
- Javascript-ID冲突的几率
- Href:当前DIV中的目标ID
- 无法获取属性'Id'使用Knockout.js的未定义或空引用API
- Javascript复选框函数:;缺少:在属性id之后"
- Twitter引导程序Typeahead-Id&标签
- 为什么 PHP 只使用“名称”标识符而不是“id”来解析 DOM 元素
- 为什么不在JavaScript中直接使用元素id作为标识符呢?
- JQuery post JSON数据抛出错误,"未引号标识符'Id'在位置0"
- 任何用于编码复杂标识符的标准函数,如html元素id/class/name