打印

BX9010: 各浏览器中对直接以 id 或者 name 属性值获取元素存在差异

作者:陆远

标准参考

根据 HTML4.01 规范中的描述,元素的 id 属性为元素指定了一个唯一标识符,在整个文档中这个标识符必须是唯一的。
而 HTML 属性属性表中则指明 id 属性可以用于除 BASE、HEAD、HTML、META、SCRIPT、STYLE、TITLE 之外的所有 HTML 元素。

元素的 name 属性仅存在于 BUTTON、TEXTAREA、APPLET、SELECT、FORM、FRAME、IFRAME、IMG、A、INPUT、OBJECT、MAP、PARAM、META 这些元素。而 name 属性在这些元素中也有不同的意义:

  • FORM:name 属性指定了表单的名称,以便可能被某些脚本引用。1
  • BUTTON、TEXTAREA、SELECT、INPUT、OBJECT:name 属性指定了控件名称(control name),FORM 元素内一个控件的 name 属性的作用域就是这个 FORM 元素。
  • FRAME、IFRAME:name 属性指定了当前框架的名称,这个名称可用于在脚本中引用这个元素,或者作为超链接的目标(target)。
  • IMG:name 属性指定了图像的名称,以便可能被某些脚本引用。1
  • A:name 属性指定了当前锚的名称,它可能指向另一个链接。这个属性的值必须具备唯一性,其作用域为当前文档。1
  • MAP:name 属性指定了 image map 的名称,与 IMG 元素的 usemap 属性相关联,创建图像与映射之间的联系。
  • PARAM:name 属性定义了插入对象的 run-time 参数。
  • META:name 属性提供了键/值对中的键(名称)。规范中未列举这个属性的合法取值。

注 1:这个属性的存在是为了向后兼容,目前应使用 id 属性来唯一标识一个元素。

关于 id 属性的更多信息,请参考 HTML4.01 规范 7.5.2 Element identifiers: the id and class attributes 中的内容。

关于 name 属性的更多信息,请参考 HTML4.01 规范如下章节中的内容:

问题描述

直接以 id 或 name 属性值获取元素不能保证在各浏览器中通用。

造成的影响

此问题可能造成在某些浏览器内通过此方法不能获取到元素对象。

受影响的浏览器

所有浏览器  

问题分析

对于直接以 id 属性值获取元素对象,除 Firefox(S) 外,其他各浏览器均可以获取到所有被测元素的对象。
对于直接以 name 属性值获取元素对象,所有浏览器均支持直接通过 name 属性值获取 IFRAME、FRAME 元素,并且获取到的对象均为子页面的 window 对象。而其他元素则出现较大差异。

下面分别通过两端测试代码检测各浏览器中直接以 id 或 name 属性值能否正确地获取到元素的对象,并且检测当出现重复的 id 或 name 属性的值时,获取到的对象类型。

  1. OK 代表可以获取到元素的对象,返回了对象的引用。
  2. Fail 代表无法获取到元素的对象。

其中 IFRAME、FRAME 元素还需要额外检测获取到的对象类型。

由于测试代码较多较长,这里不再全部贴出,具体代码请参见页面底部的“测试页面”部分的链接。

1. 通过 id 属性值

分析以下三段代码:

  1. id.html,检测 A ABBR ACRONYM ADDRESS AREA B BDO BIG BLOCKQUOTE BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DIR DIV DFN DL DT EM FIELDSET FONT FORM H1 H2 H3 H4 H5 H6 HR I IMG INPUT INS ISINDEX KBD LABEL LEGEND LI LINK MAP MENU META OBJECT OL OPTGROUP OPTION EMBED P PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR XMP 元素
  2. id_frame.html1,检测 FRAMESET FRAME 元素
  3. id_html.html2,检测 HTML HEAD STYLE SCRIPT BODY IFRAME 元素

注 1:由于 FRAMESET 与 FRAME 元素构成的框架页的特殊结构(此时页面不允许出现 BODY 元素),所以将这两个元素单独测试。
注 2:由于 HTML、HEAD、BODY 这类代表 HTML 文档结构的元素,以及 SCRIPT、STYLE 元素的特殊性,所以将这些元素与 IFRAME 一起单独测试。

列表总结如下:

id IE6 IE7 IE8 Chrome Safari Opera Firefox(Q) Firefox(S)
IFRAME OK
[window]
OK
[HTMLIFrameElement]
Fail
FRAME OK
[window]
OK
[HTMLFrameElement]
Fail
测试代码中的其他 HTML 元素1 OK
[HTMLCollection],若有重复,返回集合。
OK
[HTMLElement],若有重复,返回第一个。
Fail

注 1:这些元素包括:A ABBR ACRONYM ADDRESS AREA B BDO BIG BLOCKQUOTE BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DIR DIV DFN DL DT EM FIELDSET FONT FORM H1 H2 H3 H4 H5 H6 HR I IMG INPUT INS ISINDEX KBD LABEL LEGEND LI LINK MAP MENU META OBJECT OL OPTGROUP OPTION EMBED P PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR XMP FRAMESET HTML HEAD STYLE SCRIPT BODY

对于直接以 id 属性值获取元素对象,除 Firefox(S) 外,其他各浏览器均可以获取到所有被测元素的对象。

针对 IFRAME 及 FRAME 元素,Firefox(Q) 中获得的是元素对象自身;而 其他浏览器 中则是其内子页面的 window 对象。
针对其他元素,当出现 id 属性值重复的元素时,在 Firefox(Q) 返回的是符合这个 id 属性值的第一个元素对应的 DOM 对象;而 其他浏览器 中则是一个对象集合,集合内包含了所有符合这个 id 属性值的元素对象。


2. 通过 name 属性值

分析以下四段代码:

  1. name.html,检测 A ABBR ACRONYM ADDRESS AREA B BDO BIG BLOCKQUOTE BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DIR DIV DFN DL DT EM FIELDSET FONT FORM H1 H2 H3 H4 H5 H6 HR I IMG INPUT INS ISINDEX KBD LABEL LEGEND LI LINK MAP MENU META OBJECT OL OPTGROUP OPTION EMBED P PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR XMP 元素
  2. name_frame.html,检测 FRAMESET FRAME 元素
  3. name_html.html,检测 HTML HEAD STYLE SCRIPT BODY IFRAME 元素
  4. name_form.html1,检测 FORM 元素中的 INPUT SELECT TEXTAREA OBJECT BUTTON 元素

注 1:由于 FORM 元素对象在 DOM 中的特殊性,这里单独测试位于 FORM 元素内的各表单元素。

对于直接以 name 属性值获取元素对象,各浏览器出现较大的差异。

列表总结如下:

name IE6 IE7 IE8 Firefox(S) Firefox(Q) Chrome Safari Opera
A OK
[HTMLCollection],若有重复,返回集合。
Fail Fail OK
[HTMLCollection],若有重复,返回集合。
FRAMESET OK Fail Fail OK
FRAME OK
[window]
OK
[window]
OK
[window]
OK
[window]
IFRAME OK
[window]
OK
[window]
OK
[window]
OK
[window]
IMG OK
[HTMLCollection],若有重复,返回集合。
Fail OK
[HTMLCollection],若有重复,返回集合。
OK
[HTMLCollection],若有重复,返回集合。
MAP OK
[HTMLCollection],若有重复,返回集合。
Fail Fail Fail
META OK
[HTMLCollection],若有重复,返回集合。
Fail Fail Fail
EMBED OK
[HTMLCollection],若有重复,返回集合。
Fail OK
[HTMLCollection],若有重复,返回集合。
Fail
FORM OK
[HTMLCollection],若有重复,返回集合。
Fail OK
[HTMLCollection],若有重复,返回集合。
OK
[HTMLCollection],若有重复,返回集合。
位于 FORM 元素之外的表单元素:
INPUT OK
[HTMLCollection],若有重复,返回集合。
Fail Fail OK
[HTMLCollection],若有重复,返回集合。
OBJECT OK
[HTMLCollection],若有重复,返回集合。
Fail OK
[HTMLCollection],若有重复,返回集合。
OK
[HTMLCollection],若有重复,返回集合。
SELECT OK
[HTMLCollection],若有重复,返回集合。
Fail Fail OK
[HTMLCollection],若有重复,返回集合。
TEXTAREA OK
[HTMLCollection],若有重复,返回集合。
Fail Fail OK
[HTMLCollection],若有重复,返回集合。
BUTTON OK
[HTMLCollection],若有重复,返回集合。
Fail Fail OK
[HTMLCollection],若有重复,返回集合。
位于 FORM 元素之内的表单元素:
INPUT Fail Fail Fail Fail
OBJECT Fail Fail OK
[HTMLCollection],若有重复,返回集合。
OK
[HTMLCollection],若有重复,返回集合。
SELECT Fail Fail Fail Fail
TEXTAREA Fail Fail Fail Fail
BUTTON Fail Fail Fail Fail
测试代码中的其他 HTML 元素1 Fail Fail Fail Fail

注 1:这些元素包括:ABBR ACRONYM ADDRESS AREA B BDO BIG BLOCKQUOTE BR CAPTION CENTER CITE CODE COL COLGROUP DD DEL DIR DIV DFN DL DT EM FIELDSET FONT H1 H2 H3 H4 H5 H6 HR I INS ISINDEX KBD LABEL LEGEND LI LINK MENU OL OPTGROUP OPTION P PARAM PRE Q S SAMP SCRIPT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD TFOOT TH THEAD TITLE TR TT U UL VAR XMP HTML HEAD STYLE SCRIPT BODY

可以看到,IE 可以通过 name 属性值获取到所有拥有 name 属性的元素。

所有浏览器均支持直接通过 name 属性值获取 IFRAME、FRAME 元素,并且获取到的对象均为子页面的 window 对象。

当出现 name 属性值重复的元素时,在各浏览器中若能返回对象且对象不为 window,则均为集合,集合内包含了所有符合这个 name 属性值的元素对象。

解决方案

通过上面的测试可以看到,仅仅在通过 name 属性获取 IFRAME 和 FRAME 元素内子页面的 window 对象时,所有浏览器没有差异。
所以应避免直接以 id 或者 name 属性值获取元素,应该使用标准的 document.getElementByIddocument.getElementsByName 方法获取元素。

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Firefox 3.6.8
Chrome 6.0.472.14 dev
Safari 5.0.1
Opera 10.60
测试页面: id.html
id_frame.html
id_html.html
name.html
name_frame.html
name_html.html
name_form.html
本文更新时间: 2010-08-05

关键字

getElementById getElementsByName id name 获取 元素