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

HTMLCollection和NodeList

⛱️序言

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

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

懵逼

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

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

🎈一、基础知识

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 // trueconst 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 的区别

HTMLCollectionNodeList
集合元素的集合节点的集合
静态和动态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); // 5var newLi = document.createElement('li');oldUl.appendChild(newLi);console.log(oldLi.length); // 5var 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); // 5var newLi = document.createElement('li');oldUl.appendChild(newLi);console.log(oldLi.length); // 6 → 顺利改变 DOM 的结构</script>
</body>
</html>

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

📞三、结束语

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

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

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

🐣彩蛋 One More Thing

(:参考资料

lio_zero👉HTMLCollection和NodeList的区别

Snandy👉将HTMLCollection/NodeList/伪数组转换成数组

binyellow👉DOM操作,HTMLCollection、NodeList

爱民👉NodeList 和 HTMLCollection

(:番外篇

  • 关注公众号星期一研究室,第一时间关注优质文章,更多精选专栏待你解锁~

  • 如果这篇文章对你有用,记得留个脚印jio再走哦~

  • 以上就是本文的全部内容!我们下期见!👋👋👋

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307905.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode144. 二叉树的前序遍历(递归+迭代)

一:题目 二&#xff1a;上码 1&#xff1a;递归 class Solution { public:void preorder(TreeNode* root,vector<int>&v ) {if(root NULL) return;v.push_back(root->val);preorder(root->left,v);preorder(root->right,v);}vector<int> preorderT…

都说性能调优难?玩转这3款工具,让你秒变“老司机”!

鲁迅说过&#xff1a;菜鸟写业务&#xff0c;老鸟搭架构&#xff0c;高手玩调优。性能调优可谓是食物链顶端的技术&#xff0c;高薪面试必备良品。然而有不少的开发者&#xff0c;工作多年&#xff0c;却对性能调优几乎一无所知&#xff0c;今天就带大家掰扯掰扯&#xff0c;从…

一文梳理JavaScript中常见的七大继承方案

阐述JavaScript中常见的七大继承方案&#x1f4d6;序言&#x1f4d4;文章内容抢先看&#x1f4dd;一、基础知识预备1. 继承的定义2. 继承的方式&#x1f4da;二、6大常见继承方式1. 原型链继承 &#x1f4a1;&#xff08;1&#xff09;构造函数、原型和实例的关系&#xff08;2…

微软发布 Microsoft Edge 85 稳定版

喜欢就关注我们吧&#xff01;微软推出了 Microsoft Edge 85 稳定版&#xff08;85.0.564.41&#xff09;&#xff0c;现在正逐步向用户推送。此版本带来了以下新特性&#xff1a;收藏夹和设置的本地同步。现在可以在自己的环境中的 Active Directory 配置文件之间同步浏览器收…

leetcode94. 二叉树的中序遍历(左中右)

二:上码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* Tre…

浅谈前端路由原理hash和history

浅谈前端路由原理hash和history&#x1f3b9;序言&#x1f3b8;一、前端路由原理1、SPA2、什么时候需要路由&#x1f3b7;二、Hash模式1、定义2、网页url组成部分&#xff08;1&#xff09;了解几个url的属性&#xff08;2&#xff09;演示3、hash的特点&#x1f3ba;三、Histo…

leetcode145. 二叉树的后序遍历

一:题目 二:上码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*…

.NET Core API文档管理组件 Swagger

Swagger这个优秀的开源项目相信大家都用过&#xff0c;不多介绍了&#xff0c;这里简单记录一下使用过程。开源地址&#xff1a;https://github.com/domaindrivendev/Swashbuckle.AspNetCore在项目中添加组件Install-Package Swashbuckle.AspNetCore下面用最少的代码完成接入&a…

「3.4w字」超保姆级教程带你实现Promise的核心功能

保姆级详解promise的核心功能&#x1f4da;序言&#x1f4cb;文章内容抢先看&#x1f4f0;一、js的同步模式和异步模式1. 单线程&#x1f4a1;2. 同步模式&#x1f4a1;&#xff08;1&#xff09;定义&#xff08;2&#xff09;图例3. 异步模式&#x1f4a1;&#xff08;1&…

leetcode199. 二叉树的右视图(层序遍历03)

一:题目 二&#xff1a;上码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(n…

如何做好一个开源项目之徽章(二)

在上一篇【如何做好一个开源项目&#xff08;一&#xff09;】&#xff0c;笔者已经介绍过开源项目运作和维护的一些理念了&#xff0c;本篇开始&#xff0c;笔者将着重于介绍一些开源项目维护过程中的一些细节&#xff0c;比如徽章、构建等等。由于最近经常出差&#xff0c;所…

值得关注的HTML基础

值得关注的HTML基础&#x1f973;序言&#x1f60b;一、网页三大元素&#x1f61c;二、HTML简介1. 定义2. 发展历史&#x1f61d;三、HTML结构1. 引例阐述2. 特点3. HTML页面结构&#xff08;1&#xff09;DOCTYPE&#xff08;2&#xff09;html&#xff08;3&#xff09;head&…

leetcode637. 二叉树的层平均值(层序遍历04)

一:题目 二&#xff1a;上码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(n…

leetcode429. N 叉树的层序遍历(层序遍历05)

一:题目 二&#xff1a;上码 /* // Definition for a Node. class Node { public:int val;vector<Node*> children;Node() {}Node(int _val) {val _val;}Node(int _val, vector<Node*> _children) {val _val;children _children;} }; */class Solution { publi…

10分钟带你探索css中更为奇妙的奥秘

10分钟带你探索css中更为奇妙的奥秘&#x1f4d6;序言&#x1f4c3;一、css是啥1. CSS是什么2. 诞生背景3. 基础规则&#xff08;1&#xff09;一些基础规则&#xff08;2&#xff09;其他重要的语法&#xff08;3&#xff09;选择器&#xff08;4&#xff09;层叠与继承1&…

将微服务部署到 Azure Kubernetes 服务 (AKS) 实践

介绍本文的目的是&#xff1a;通过使用 DockerHub 和 Azure Kubernetes Service (AKS) 将之前 使用 .NET 和 Docker 构建的微服务 部署到微软 Azure 云上&#xff0c;来介绍微服务的基本部署过程。推送到 Docker HubDocker Hub 是世界上最大的容器镜像库和社区。许多产品&#…

leetcode 515. 在每个树行中找最大值(层序遍历06)

一:题目 二&#xff1a;上码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(n…

前端只是切图仔?来学学给开发人看的UI设计

给开发人看的UI设计&#x1f5bc;️序言&#x1f3a8; 一、背景1. 想做一个好的作品2. 没有专业UI&#x1f9f5;二、功能导向1. 设计中最重要的事2. 例子阐述2. 简约设计3. 设计简单的、完整的功能&#x1f9f6;三、设计原则1. 层级&#xff08;1&#xff09;层级是什么&#x…

Debian 新负责人发表演讲:Debian 的现状与面临的一些问题

喜欢就关注我们吧&#xff01;Debian GNU/Linux 年度主要的会议 DebConf20 已于近期举办&#xff0c;4 月份新当选的 Debian 项目负责人 Jonathan Carter 在会上发表了演讲&#xff0c;概述了 Debian 的现状与面临的一些问题。Debian 的财务稳定在 $896065 美元左右&#xff0c…

leetcode116. 填充每个节点的下一个右侧节点指针(层序遍历07)

一:题目 二:上码 /* // Definition for a Node. class Node { public:int val;Node* left;Node* right;Node* next;Node() : val(0), left(NULL), right(NULL), next(NULL) {}Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}Node(int _val, Node* _left,…