一、HTMLCollection
HTMLCollection对象是一个包含了元素(元素顺序为文档流中的顺序)的通用集合(generic collection), 它提供了用来从该集合中选择元素的方法和属性。
HTML DOM 中的 HTMLCollection
是即时更新的(当其所包含的文档结构发生改变时, 它会自动更新, 所以遍历的时候需要注意.
注意:由于历史原因(DOM4之前,实现该接口的集合只能包含 HTML 元素),该接口被称为
HTMLCollection
。DOM有个节点树的概念, 节点(node)有不同种类, 例如*元素节点、文本节点、属性节点… HTMLCollection中包含的HTML元素实际上就是元素节点***
nodeType一共有12种类: 元素节点 , 属性节点, 文本节点 , CDATA节点 , 实体引用名称节点, 实体名节点 , 处理指令节点 , 注释节点 , 文档节点 , 文档类型节点 , 文档片段节点, DTD声明节点
属性:
- HTMLCollection.length
返回集合当中子元素的数目.
使用像element.getElementsByTagName()等方式获取元素的时候返回的就是HTMLCollection对象而不是数组, 所以无法使用forEach这样的数组方法遍历, 不过使用for循环遍历是可以的. 不过可以使用Array.from(someHTMLCollection)这样的方式将其转换成数组.
方法:
- HTMLCollection.item() 通过索引返回其中的元素
- HMLCollection.namedItem()
根据 Id
返回指定节点,或者在不存在id的情况下根据字符串所表示的 name
属性来匹配。根据 name
匹配只能作为最后的依赖,并且只有当被引用的元素支持 name
属性时才能被匹配。如果不存在符合给定 name
的节点,则返回 null
。
二、NodeList
NodeList
对象是一个节点的集合, 是由Node.childNodes
和document.querySelectorAll()
返回的. NodeList是一个类数组(Array-like
)的对象.
在一些情况下, NodeList
是一个实时的集合, 也就是说如果文档中的节点树发生变化, 已经存在的实时NodeList
对象也会随之变化. 例如, Node.childNodes
是实时的.
1 | const parent = document.getElementById("parent"); |
在其他情况下, NodeList
是一个静态集合, 也就意味着随后对文档对象模型的任何改动都不会影响集合的内容. 比如document.querySelectorAll()
会返回一个静态的NodeList
. 最好牢记这种不同, 尤其是在对NodeList
进行遍历的时候.
属性:
- NodeList.length()
方法:
-
Returns an
iterator
, allowing code to go through all key/value pairs contained in the collection. (In this case, the keys are numbers starting from 0 and the values are nodes.) -
Executes a provided function once per
NodeList
element, passing the element as an argument to the function. -
Returns an
iterator
, allowing code to go through all the keys of the key/value pairs contained in the collection. (In this case, the keys are numbers starting from 0.) -
Returns an
iterator
allowing code to go through all values (nodes) of the key/value pairs contained in the collection.
总结:
二者的主要区别:
NodeList
中可包含所有12中节点类型,HTMLCollection
中只能包含元素节点这一种.NodeList
是类数组对象, 拥有forEach()
,entries()
,keys()
等方法而HTMLCollection
没有.HTMLCollection
是实时的, 而NodeList
既可以是实时(node.childNodes
返回的是实时的)也可以是静态的(node.querySelectorAll()
返回的是静态的).
另外提一下, 这里谈论的NodeList
的静态集合跟使用jQuery
获取元素是相似的, 都是获取了就不变了. 好像有点像Linux
上做快照(snapshot
), 就记录那一瞬间, 哈哈.
封装一个isLive函数
上面已经写得很清楚了, 记住区别就行. 下面介绍一下stackoverflow上一位答主判断HTMLCollection
和NodeList
什么时候静态什么时候实时的代码, 或许可以帮助理解.
1 | <!DOCTYPE html> |
isLive
函数做的事情就是: 先获取集合, 将其lengh
赋值个len1
, 然后从集合里面克隆一个元素并且添加到body
下面, 接着将length赋值给len2
, 然后为了不影响页面而删除添加的元素.如果是实时的那么集合的lenght肯定会跟着变化, 第二次赋值时的lengh
就会和比第一次大1; 反之如果是静态的那么length
根本不会有变化. 所以代码最后就比较了 len1
和 len2
相不相等, 做出了静态与实时的判断.
未来走势
w3c的 Document Object Model (Core) Level 1文档里面提到node的属性childNodes的时候是这样说的:
childNodes
: A NodeList
that contains all children of this node. If there are no children, this is a NodeList
containing no nodes. The content of the returned NodeList
is *”live”* in the sense that, for instance, changes to the children of the node object that it was created from are immediately reflected in the nodes returned by the NodeList
accessors; it is not a static snapshot of the content of the node. This is true for every NodeList
, including the ones returned by the getElementsByTagName
method.
上面提到了getElementByTagName
, 而且把它也当成了NodeList而不是我们前面说的HtmlCollection. 卧槽, 怎么冲突了?
w3c的DOM4文档里面的 4.2.6节 Old-style collections: NodeList
and HTMLCollection
是这么说的:
A collection is an object that represents a lists of DOM nodes. A collection can be either live or static. Unless otherwise stated, a collection must be live.
If a collection is live, then the attributes and methods on that object must operate on the actual underlying data, not a snapshot of the data.
它这意思就是说只要是collection, 无论NodeList还是HTMLCollection都是实时(live)的. 所以可能未来都是实时的了吧,不过现在还不完全是这样.
参考: