NodeList 和 HTMLCollection之间的关系?

关注者
158
被浏览
21,082

5 个回答

历史上的DOM集合接口。主要不同在于HTMLCollection是元素集合而NodeList是节点集合(即可以包含元素,也可以包含文本节点)。所以 node.childNodes 返回 NodeList,而 node.children 和 node.getElementsByXXX 返回 HTMLCollection 。

唯一要注意的是 querySelectorAll 返回的虽然是 NodeList ,但是实际上是元素集合,并且是静态的(其他接口返回的HTMLCollection和NodeList都是live的)。事实上,将来浏览器将增加 queryAll 接口取代现在的 querySelectorAll,返回 Elements 是 Array 的子类(因而可以使用Array上的forEach、map等方法)。


补充:答

@zq bai

我讲的api可以直接到

dom.spec.whatwg.org/

上看。

历史上dom1、dom2乃至dom3标准都是分core/XML和HTML部分的。getElementsByTagName是在core里的(即XML也有的),所以不可能返回HTMLCollection。但是现在的dom标准已经不分core和html了,反映的是浏览器的实现。

而现代浏览器的api的兼容起点是IE6(嗯,就是如此)。所以你可以看IE6是如何的。IE6里dom对象是没有构造器,也得不到原型。不过有个事情可以用来判断,NodeList跟HTMLCollection有个差异是前者没有namedItem()方法后者是有的。所以拿个IE6试验下即知。另外一种方式是看IE8。IE8的DOM有了constructor属性,你直接console.log()打出来看就知道了。

泻药

这种问题还是挺难说清楚的。

不同浏览器由于历史原因实现混乱

从规范开始说

DOM 的初衷是为解析 XML 设计

之后沿用到HTML上

查查规范列表就能发现

历史标准通常分两部分来内容来说

分别是 Core 和 HTML

Core 部分提供最基础的 XML 解析API说明

HTML 部分专为 HTML 中的 DOM 解析添加其特有的 API

NodeList 接口说明是在 Core 中体现的

HTMLCollection 接口是在 HTML 中特有的

规范中两者都返回的是(live的) Node 集合与 Node(取索引)

其中后者多了一个nameItem 方法可用

由于规范不同时期的迭代变化

以及对于实现者来说的无强制决定性

返回一组节点列表的 API 具体设计

并不(一定)需要遵从于 DOM HTML 规范

也可以遵循 DOM Core

(当时实现时候 DOM HTML 规范未完善未定稿、抑或是降低实现复杂度等等原因)


那么不同的浏览器实现

可能会实现(继承) NodeList 接口(或类)

也可能会实现(继承) HTMLCollection 接口(或类)

甚至可能无视规范

让含有 nameItem 方法的对象依然让前端探测上看上去像是 NodeList 接口(类)的实现

或者整好相反

(比如 早期 IE 版本 等)

时至今日

whatwg 这种厂商联盟性质的规范组织出现

让 DOM 规范更加贴合实际

DOM Living 标准的不断演变让这部分内容在联盟厂商内实现变得有约束性

所以在最新的 DOM Living 中

NodeList 相关的返回的是 Node 集合与 Node(取索引)

HTMLCollection 相关的返回是 Element 集合与 Element(取索引)

后者同样多一个 nameItem 方法

两者同样可能是 live 或 static 的集合。