多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[toc] >以下内容基本整理自[大漠のJavaScript学习笔记:动态集合](https://www.w3cplus.com/javascript/dom-dynamic-collection.html) ## 树状图 ### 从原型链看 ![](https://box.kancloud.cn/0522b1c386b2bd517207e5e2228771e4_1555x573.png) ### 从节点包含看 ![](https://www.w3cplus.com/sites/default/files/blogs/2018/1804/js-dom-2.png) ![](https://www.w3cplus.com/sites/default/files/blogs/2018/1804/js-dom-8.jpeg) ## NodeList、HTMLCollection、NamedNodeMap DOM中有三个动态集合,它们分别是NodeList、HTMLCollection和NamedNodeMap,而这三个集合都是类数组对象。具有数组的表现方式,但没有不具备数组的方法。在实际使用时,需要将类数组转换为数组。更为重要的是,它们都是动态的,是有有生命有呼吸的对象,会实时更新查询DOM结构。除此之外,动态集合将会有动态NodeList和静态NodeList之分,并且动态NodeList要比静态NodeList要快。其根本原因在于两者对象不同。这也是为什么说getElementsByTagName() 速度比 querySelectorAll() 快的根本原因所在。 DOM是JavaScript中重要部分之一,在DOM中有一个动态集合。这个动态集合包含节点的集合(NodeList)、元素属性的集合(NamedNodeMap)和HTML元素的集合(HTMLCollection)。这三个对象都是类数组(Array-like),具有像数组一样的特性。更为重要的是,它们都是动态的,是有有生命有呼吸的对象,会实时更新查询DOM结构。 ### NodeList ``` <!DOCTYPE html> <html> <head> <title>DOM Tree Sample Document</title> </head> <body> <div id="box"> <!-- 标题 --> <div>Title</div> <div class="item">Item1</div> <div class="item">Item2</div> <div class="item">Item3</div> <div class="item">Item4</div> <div class="item">Item5</div> </div> </body> </html> ``` #### 获取NodeList集合的方法一:`.childNodes` ``` let box = document.getElementById('box'); let children = box.childNodes; console.log(children, children.length) ; console.log(children instanceof NodeList); ``` ![](https://www.w3cplus.com/sites/default/files/blogs/2018/1805/dom-collection-3.png) #### 获取NodeList集合的方法二:`querySelector` ``` let divs = document.querySelectorAll('div') ; console.log(divs, divs.length); console.log(divs instanceof NodeList); ``` ![](https://www.w3cplus.com/sites/default/files/blogs/2018/1805/dom-collection-4.png) #### 遍历NodeList NodeList可以通过`[]表达式`来访问,也可以通过`item()`方法来访问。而且它也有length属性,可以访问元素个数。虽然JavaScript中的数组可以修改length属性,但NodeList是一个类数组,而且它是页面一片区域的DOM结构映射。所以不要修改NodeList对象的length值。 ![](https://www.w3cplus.com/sites/default/files/blogs/2018/1805/dom-collection-6.png) #### 两者获取到的NodeList的区别 Node的childNodes和document.querySelectAll()对应的NodeList是有所不同的,前者是`动态的`,后者是`静态的`。 ![](https://www.w3cplus.com/sites/default/files/blogs/2018/1805/dom-collection-5.png) ### HTMLCollection HTMLCollection对象与NodeList对象类似,都是节点的集合,返回的都是类数组对象。但也有其不同之处,其中NodeList集合包含着node节点中12种节点,而HTMLCollection**仅**包含`elements元素节点`的集合。 #### HTMLCollection的获取方式 HTMLCollection的集合可以通过`getElementsByTagName()`、`getElementsByName()`、`document.anchors`、`document.forms`、`document.images和documnet.link`s等方式来获取。比如: ``` // 获取NodeList let nodeList = document.getElementById('box').childNodes console.log(nodeList, nodeList.length) // 获取HTMLCollection let htmlCollectionList = document.getElementsByTagName('div') console.log(htmlCollectionList, htmlCollectionList.length) ``` ![](https://www.w3cplus.com/sites/default/files/blogs/2018/1805/dom-collection-7.png) #### HTMLCollection的遍历 HTMLCollection和NodeList类似,都是类数组,同样可以使用`[]`或者`item()`来访问。 ### NamedNodeMap DOM中的Element节点是唯一拥有attributes属性的一种节点类型。而attributes属性中就包含NamedNodeMap集合。NamedNodeMap集合的元素拥有nodeName和nodeValue属性(属于atrributes类型),分别表示元素节点名称和值。 ### 三者的异同 虽然NodeList、HTMLCollection和NamedNodeMap都是DOM的动态集合,但三者之间也有差异。先来看三者相同之处: - 三者都具有length属性 - 三者都有item()方法 - 三者都是动态的,如果对NodeList和HTMLCollection中的元素进行操作都会直接反映到DOM中,因此如果一次性直接在集合中进行DOM操作,开销非常大 另外三者也有不同之处: - NodeList里面包含了所有的节点类型 - HTMLCollection里面只包含元素节点 - NamedNodeMap里面包含了Attribute的集合,例如id、title、class等,集合中的每一个元素都是attr类型 - 三者所提供的方法也有不同,例如HTMLCollection中提供了namedItem(),而NodeList和NamedNodeMap两个集合中没有namedItem()方法 ## 动态NodeList和静态NodeList 动态 NodeList 对象在浏览器中可以更快地被创建并返回,因为他们不需要预先获取所有的信息, 而静态 NodeList 从一开始就需要取得并封装所有相关数据. 再三强调要彻底了解这一点, WebKit 的源码中对每种 NodeList 类型都有一个单独的源文件: - DynamicNodeList.cpp - StaticNodeList.cpp 两种对象类型的创建方式是完全不同的。 使用getElementsByTagName()方法我们得到的结果就像是一个对象的索引,而通过querySelectorAll()方法我们得到的是一个对象的克隆;所以当这个对象数据量非常大的时候,显然克隆这个对象所需要花费的时间是很长的。 ### 选择使用 在以后需要用到获取元素集合的方法的时候,我们就要根据不同的场景来选择使用不同的方法了。如果你不需要一个快照,那就选择使用getElementsByTagName()方法,如果你需要一个快照来进行复杂的CSS查询,或者复杂的DOM操作的话,那就选择使用querySelectorAll()方法。