你可能没有听说过 js中的 DOM操作还有这个: HTMLCollection 和 NodeList

简介: 犹记得上回有一次面试的时候被问到 htmlCollection 和数组的关系。当时的我心里想的是, html 中的集合和数组的关系,那解题就是说 set 和数组的关系?


32.png⛱️序言


犹记得上回有一次面试的时候被问到 htmlCollection 和数组的关系。当时的我心里想的是, html 中的集合和数组的关系,那解题就是说 set 和数组的关系?

于是……面试官当下立即纠正我, htmlCollection 是单词连在一起的,是 js 的一个内容。当时我可能是想……找个地洞钻……

1.png

不会的咋还是得虚心接收,查漏补缺还是比较合理。经过一系列的资料查询和总结之后,得出以下总结。

下面开始进入本文的讲解~🙋


🎈一、基础知识


1. 定义


(1)HTMLCollection

  • HTMLCollection 表示一个包含了元素(元素顺序为文档流中的接口)的集合(通用集合),还提供了从该集合中选择元素的属性和方法。
  • 例如使用 getElementsByTagName() 方法返回的就是一个 HTMLCollection 对象。


(2)NodeList

  • NodeList 对象是节点的集合。
  • 通过以下方法,可以获取到 NodeList 对象。主要有:在一些旧版本浏览器中的方法,比如 getElementsClassName() 方法,返回的是 NodeList 对象,而不是 HTMLCollection 对象。所有浏览器的 Node.childNodes 属性返回的都是 NodeList 对象。大部分浏览器的 document.querySelectorAll() 返回的是 NodeList 对象。
  • 我们可以通过以下代码进行验证:
document.body.childNodes instanceof NodeList // true
document.querySelector('body') instanceof NodeList // true or false
document.getElementByClassName('body') instanceof NodeList // true or false
复制代码


2. 属性和方法


(1)HTMLCollection

HTMLCollection 对象中的属性和方法,举例两个:

  • item(index) —— 返回 HTMLCollection指定索引的元素,如果不存在则返回 null
  • length (只读) —— 返回 HTMLCollection 中元素的数量

接下来用一个例子来进行阐述验证。具体代码如下:

document.getElementsByTagName('body') instanceof HTMLCollection // true
const htmlCollection = document.getElementsByTagName('body')
console.log(htmlCollection.item(0)) // <body>...</body>
console.log(htmlCollection.length()) // 1
复制代码


(2)NodeList

NodeList 对象中的属性和方法主要有以下几种。包括:

  • item() —— 返回某个元素基于文档数的索引;
  • length() —— 返回 NodeList 中的节点数量;
  • NodeList.forEach() —— 该方法用于遍历 NodeList 中的所有成员。它接收一个回调函数作为参数,每遍历一回就要执行这个回调函数一次,用法与数组实例的 forEach 方法是完全一致的;
  • NodeList.keys()/values()/entries() —— 对于这三个方法来说,它们都会返回一个 ES6遍历器对象,可以通过 for…of… 来进行循环遍历,以便于获取每一个成员的信息

同时,需要注意以上三者的区别,分别如下:

  • keys() —— 指的是返回键名的遍历器;
  • values() —— 指的是返回键值的遍历器;
  • entries() —— 指的是返回的遍历器要同时包含键名和键值的信息。

我们写点代码来论证以上内容。具体代码如下:

const nodelist = document.querySelectorAll('body')
console.log(nodelist.item(0)) // <body>...</body>
console.log(nodelist.length) // 1
console.log(nodelist.forEach(item => console.log(item))) // <body>...</body>
for(var key of nodelist.keys()) {
  console.log(nodelist[key]) // <body>...</body>
}
for(var value of nodelist.values()) {
  console.log(value) // <body>...</body>
}
for(var entry of nodelist.entries()) {
  console.log(entry) // [0, body]
}
复制代码


🪁二、异同点


1. HTMLCollection 与 NodeList 的区别


HTMLCollection NodeList
集合 元素的集合 节点的集合
静态和动态 HTMLCollection 是动态绑定的,是一个动态集合。DOM 树发生变化,HTMLCollection 也会随之变化,说明其节点的增删是敏感的 NodeList 是一个静态集合,其不受 DOM 树元素变化的影响;相当于是 DOM 树、节点数量和类型的快照,也就是说对节点进行增删操作时,NodeList 是感觉不到的。但是对节点内部内容修改,是可以感觉得到的,比如修改 innerHTML
节点 不包含属性节点和文本节点 只有 NodeList 对象有包含属性节点文本节点
元素获取方式 HTMLCollection 元素可以通过 name,id 或 index 索引来获取 NodeList 只能通过 index 索引来获取
伪数组 HTMLCollection 和 NodeList 都是类数组,不是数组,只是长得像数组而已。所以无法使用数组的方法,比如: pop(),push(),或 join() 等等 与 HTMLCollection 一样


2. querySelectorAll 和 getElementsByTagName 的区别

在上述的表格中我们可以了解到, HTMLCollection 是动态集合,当 DOM 树发生变化时, HTMLCollection 也会随之改变。而 NodeList 是静态集合,当 DOM 树发生变化时, NodeList 不会受到 DOM 树变化的影响。我们来举两个例子进行阐述说明。


(1)querySelectorAll

先附上代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>htmlCollection和NodeList</title>
</head>
<body>
    <ul>
        <li></li>
        <li></li>
        <li>MondayLab</li>
        <li></li>
        <li></li>
    </ul>
    <script>
        var oldUl = document.querySelectorAll('ul')[0];
        var oldLi = document.querySelectorAll('li');
        console.log(oldUl); // NodeList[body]
        console.log(oldLi.length); // 5
        var newLi = document.createElement('li');
        oldUl.appendChild(newLi);
        console.log(oldLi.length); // 5
        var length = oldLi.length - 1;
        oldLi[length].innerHTML = 'monday';
        console.log(oldLi[length].innerHTML); // monday 
        console.log(oldLi.length); // 5 → 虽然通过innerHTML可以读到文本节点的内容,但是长度依旧不变,还是5
    </script>
</body>
</html>
复制代码

大家可以看到,使用 querySelectorAll 来获取 <li> ,返回的是一个 NodeList 的集合。且当页面 DOM 结构发生改变时,其长度不会发生任何的改变。但是当改变 innerHTML 时,则文本节点的内容会发生改变。值得注意的是,即使 innerHTML 改变 DOM 的结构,但长度依旧是不变的,还是 5


(2)getElementsByTagName

先附上代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTMLCollection</title>
</head>
<body>
    <ul>
        <li></li>
        <li></li>
        <li>MondayLab</li>
        <li></li>
        <li></li>
    </ul>
    <script>
        var oldUl = document.getElementsByTagName('ul')[0];
        var oldLi = document.getElementsByTagName('li');
        console.log(oldUl); // HTMLCollection[body]
        console.log(oldLi.length); // 5
        var newLi = document.createElement('li');
        oldUl.appendChild(newLi);
        console.log(oldLi.length); // 6 → 顺利改变 DOM 的结构
    </script>
</body>
</html>
复制代码

大家可以看到,使用 getElementByTagName 时,获取的是一个 HTMLCollection 集合,这个时候说明对节点进行增删操作时,页面的 DOM 结构会发生改变,且HTMLCollection实时地获取到集合的长度。


📞三、结束语


写到这里的时候,不得不感概 jsDOM 操作是如此的强大,也突然就明白了自己之前写代码的时候为啥会遇到那么多坑。如果在学习之初就追溯于原理,可能跳的坑应该就能少很多了。

讲到这里,关于 HTMLCollectionNodeList 的内容就结束啦!希望对大家有帮助~

彩蛋有几篇我看过还比较好理解的文章,有需要可以当扩展知识进行扩充哦~



相关文章
|
1月前
|
JavaScript
DOM 节点列表长度(Node List Length)
`length`属性用于获取DOM节点列表的长度,即节点数量。通过遍历这个属性,可以访问和处理所有节点。例如,示例代码加载&quot;books.xml&quot;,获取所有&quot;title&quot;节点,并依次输出它们的第一个子节点的值。
|
7天前
|
JavaScript 前端开发
js之DOM 文档对象模型
js之DOM 文档对象模型
8 1
js之DOM 文档对象模型
|
9天前
|
存储 JavaScript
DOM 节点列表长度(Node List Length)
名为 &quot;title&quot; 的元素节点,并存储在节点列表 x 中。通过循环遍历节点列表,利用 length 属性确定列表中的节点数量,并依次访问每个节点的 childNodes[0](即节点内的文本内容),将其输出到文档中。
|
8天前
|
XML JavaScript 前端开发
JavaScript中的DOM解析器DOMParser api的讲解
`DOMParser`能将XML或HTML源码字符串解析成DOM `Document`。通过`new DOMParser()`创建实例,使用`.parseFromString(string, type)`方法进行解析,其中`string`为待解析的字符串,`type`指定解析类型如`text/html`或`text/xml`等,返回一个`Document`对象。例如,可解析包含`&lt;p&gt;666&lt;/p&gt;`的字符串并获取其文本内容`666`。
13 1
|
11天前
|
存储 JavaScript
DOM 节点列表长度(Node List Length)
名为 &quot;title&quot; 的元素节点,并存储在节点列表 x 中。通过 &quot;length&quot; 属性确定 x 的长度(即 &quot;title&quot; 节点总数)。利用 for 循环遍历整个列表,访问每个 &quot;title&quot; 节点的第一个子节点的值,并将其写入文档。
|
25天前
|
JavaScript
DOM 节点列表长度(Node List Length)
`length`属性定义了节点列表的长度(即节点数量)。可通过此属性遍历节点列表。
|
2天前
|
存储 JavaScript
DOM 节点列表长度(Node List Length)
名为 &quot;title&quot; 的元素节点,并存储在节点列表 x 中。通过 &quot;length&quot; 属性确定 x 的长度(即 &quot;title&quot; 节点总数)。利用 for 循环遍历整个列表,访问每个 &quot;title&quot; 节点的第一个子节点的值,并将其写入文档。
|
26天前
|
XML JavaScript 数据格式
DOM 节点列表长度(Node List Length)
`length`属性表示DOM节点列表的长度。在示例中,通过加载&quot;books.xml&quot;到`xmlDoc`,并使用`getElementsByTagName(&quot;title&quot;)`获取所有标题节点,然后利用`for`循环遍历整个节点列表,每次迭代通过`childNodes[0].nodeValue`访问每个节点的第一个子节点的值并输出。此方法可用于处理XML或HTML文档中的节点列表。 **Markdown格式:** `length`属性表示DOM节点列表的长度。
|
4天前
|
存储 JavaScript
DOM 节点列表长度(Node List Length)
名为 &quot;title&quot; 的元素节点,并存储在节点列表 x 中。通过 &quot;length&quot; 属性确定 x 的长度(即 &quot;title&quot; 节点总数)。利用 for 循环遍历整个列表,访问每个 &quot;title&quot; 节点的第一个子节点的值,并将其写入文档。
|
4天前
|
JavaScript 前端开发
js之DOM 文档对象模型
js之DOM 文档对象模型