NodeList的使用

633 阅读3分钟

引言

在使用JavaSscrpi的NodeList时。本小白最初误以为这就是简单的Node型的数组,想要用它调用一些数组方法,但在运行过程中却出现了报错。如下所示

 const ps=document.getElementsByTagName("p");
        const p=document.createElement("p");
        p.innerText="good";
        ps.push(p);

报错提示: *Uncaught TypeError: ps.push is not a function*

但在查阅相关资料后,才发现NodeList是JavaSrpit中的一个类似数组的对象(Like Array Object),是节点的集合对象,并非是数组。

NodeLisde的使用

为什么NodeList不是数组?

NodeList 对象在某些方面和数组非常相似,看上去可以直接使用从 Array.prototype 上继承的方法。然而,除了 forEach 方法,NodeList 没有这些类似数组的方法。 虽然NodeList不是数组,但是还是可以通过for循环进行遍历.

for (var i = 0; i < myNodeList.length; ++i) {
  var item = myNodeList[i]; 
}

此外NodeList上也有一些其他方法

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

  • NodeList.entries()

    返回一个迭代器,允许代码遍历集合中包含的所有键/值对。 (在这种情况下,键是从 0 开始的数字,值是节点。

  • NodeList.forEach()

每个 NodeList 元素执行一次提供的函数,将元素作为参数传递给函数。

  • NodeList.keys()

    返回一个迭代器,允许代码遍历集合中包含的键/值对的所有键。 (在这种情况下,键是从 0 开始的数字

  • NodeList.values()

    返回一个迭代器,允许代码遍历集合中包含的键/值对的所有值(节点)

NodeList是基于DOM的实时查询

NodeList对于DOM文档结构变化而言是“实时的”,文档结构的变化会实时的在它们身上反映出来,因此他们的值也始终代表文档的最新状态。废话少说上代码。

        let divs=document.getElementsByTagName("div");
        for(let i=0;i<divs.length;++i){
            let div=document.createElement("div");
            div.innerText="NodeList";
            document.body.appendChild(div);
        }

这个代码看上去没有问题,但实际上会导致无限循环。

第一行取得了包含文档中所有<div>元素的HTMLCollection.

因为这个集合是“实时的,所以任何时候只要向页面中添加一个新<div>元素,再查询这个集合就会多一项。因为浏览器不希望保存每次创建的集合,所以就会在每次访问时更新集合。

这样就会出现前面使用循环的例子中所演示的.每次循环开始,都会求值“i<divs.length” 这意味着要执行所有<div>元素的查询,因为循环体每次创建并向文档新增一个<div>,所以每次循环divs.length的值也会递增。因为两个值都会递增,所以i将永远不会等于divs.length. 

那么怎么解决这个问题呢?

我们采用的方案是在迭代NodeList时,最好再初始化一个变量保存当时查询的长度,如下所示

        let divs=document.getElementsByTagName("div");
        for(let i=0,len=divs.length;i<len;++i){
            let div=document.createElement("div");
            div.innerText="NodeList";
            document.body.appendChild(div);
        }

一般来说,最好要限制操作NodeList的次数,因为每次操作都会搜索整个文档,所以最好吧NodeList存储起来

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

最好牢记这种不同,尤其是在当你选择 NodeList 中所有项遍历的方式,或缓存它的长度的时候。