概述
旧样式集合(Old-style):NodeList 和 HTMLCollection。
集合(collection)是表示节点列表的对象。集合可以是实时或静态的。除非另有说明,集合必须是实时的(live)。
如果集合是实时的,那么该对象上的属性和方法必须对实际的底层数据操作,而不是数据的快照。
创建集合时,过滤器(filter)和根(root)将与其关联。
然后,集合表示根集于根集合的子树的视图,仅包含与给定过滤器匹配的节点。视图是线性的。在没有相反的特定要求的情况下,集合中的节点必须以树的顺序排序。
NodeList
NodeList 对象是节点的集合。它是由 Node.childNodes 和 document.querySelectorAll 所返回的。
有时,它是一个实时的集合,例如 Node.childNodes。我们来看个示例:
var parent = document.getElementById('parent');
var child_nodes = parent.childNodes;
console.log(child_nodes.length); // 我们得到了 "2"
parent.appendChild(document.createElement('div'));
console.log(child_nodes.length); // 此时输出 "3"
这很好的证明了它是一个动态的节点。
而 document.querySelectorAll 所返回的节点却是静态的,也就是一个快照。也就意味着随后对 DOM 的任何改动都不会影响集合的内容。
NodeList 接口表示由数字(从零开始)索引的节点的有序集合。因此它拥有 length 属性。
它就是一个类数组对象。
比如我们现在创建一个 ul 列表:
- You
- And
- Me
接着我们使用 NodeList 来返回它的子节点:
let ul = document.getElementById('ul');
console.log(ul.childNodes);
返回的结果如下所示:
我们可以从控制台的结果看出,它确实返回了一个 NodeList 集合。
当然,我们既然有 length 属性,那必然可以返回某一个节点,不然怎么叫“类数组对象”呢?
我们可以使用 collection.item(index)
或者 collection[index]
返回节点中某一个我们需要的节点。我们一般使用后者,因为它更方便。
还是上面的例子,我们来返回其中的一个节点吧:
console.log(ul.childNodes[2]);
最终返回结果:
好了,我们再来说说 querySelectorAll 为什么是静态的吧,我们来证明它。
首先,我们先获取 ul 列表中所有的 li,接着输出它:
let lis = document.querySelectorAll('li');
console.log(lis);
结果如下:
而此时,我们在 ul 中动态地添加一个 li,并输出它 :
let li = document.createElement('li');
ul.appendChild(li);
li.innerHTML = 'Others';
console.log(lis);
最终结果如下:
第二次的输出结果仍然是 3 个,而我们的 HTML 结构中却多了一个 li。 这就证明了,querySelectorAll 确实是一个静态方法。
HTMLCollection
HTMLCollection 对象是元素的集合。
注意它们之间的区别:NodeList 返回的是各节点;而 HTMLCollection 返回的是元素节点。
官方文档中有下列这句话,需要我们谨慎对待它:
HTMLCollection 是一个历史的工件,我们不能从 web 中摆脱它。虽然开发人员当然欢迎继续使用它,但新的 API 标准设计者不应该使用它。
同样的,它也拥有 length 属性,以及可以使用方括号[] 来访问其中的某一特定元素。
我们来看它和 NodeList 的区别吧。同样还是我们上面提到的那个 ul 列表:
let ul = document.getElementById('ul');
console.log(ul.children);
这一次,我们将 childNodes
换成了 children
。它的结果发生了变化:
这次我们也很清楚的看到了,它变成了 HTMLColletion。
至于这两个集合之间的关联,那是历史问题了,这里就不再做深究了。你只需要知道 NodeList 最初设计是给 XML 使用的,而 DOM 中就会返回元素节点和文本节点,通常就产生了我们不想要的东西,比如 IE6 ~ 8 会返回我们的注释,也将它们作为了节点;因此,后来也就诞生了 HTMLCollection,它就只返回元素节点,这通常是我们想要的。例如 getElements* 系列:document.getElementsByTagName
、document.getElementsByClassName
、document.getElementsByName
等等。
其它的就不需要知道了。本节到此结束。