NodeList

在一个折腾的javascript框架中querySelectorAll ,发现会报错。几经折腾发现原来querySelectorAll 返回的是一个Nodelist,而非数组(主要经常使用querySelectorAll ()[index]而造成错觉),联想到该方法在浏览器和IDE下会智能提示出item属性。

既然已经踩了坑,就记录下吧!

NodeList 对象是一个节点的集合,是由 Node.childNodesdocument.querySelectorAll 返回的.

属性

length

NodeList 对象中包含的节点个数.

方法

item ( idx )
返回NodeList对象中指定索引的节点,如果索引越界,则返回null.等价的写法是nodeList[idx], 不过这种情况下越界访问将返回undefined.

描述

一个“有时实时”的集合

大多数情况下,NodeList 对象都是个实时集合。意思是说,如果文档中的节点树发生变化,则已经存在的 NodeList 对象也可能会变化。例如,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”

在另一些情况下,NodeList 是一个静态集合,也就意味着随后对文档对象模型的任何改动都不会影响集合的内容。document.querySelectorAll 返回一个静态的 NodeList。

特别是当你选择如何遍历 NodeList 中所有项,或缓存列表长度的时候,最好牢记这种区分。

 

为什么 NodeList 不是数组?

NodeList 对象在某些方面和数组非常相似,看上去可以直接使用从 Array.prototype 上继承的方法。然而,NodeList 没有这些类似数组的方法。

JavaScript 的继承机制是基于原型的。数组元素之所以有一些数组方法(比如 forEach 和 map),是因为它的原型链上有这些方法,如下:

myArray –> Array.prototype –> Object.prototype –> null (想要获取一个对象的原型链,可以连续的调用 Object.getPrototypeOf,直到原型链尽头).

forEach, map这些方式其实是 Array.prototype 这个对象的方法。

和数组不一样,NodeList的原型链是这样的:

myNodeList –> NodeList.prototype –> Object.prototype –> null

NodeList.prototype 只有一个 item 方法,没有 Array.prototype 上的那些方法,所以 NodeList 对象用不了它们。