[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()方法。
- 空白目录
- window
- location
- history
- DOM
- 什么是DOM
- JS盒子模型
- 13个核心属性
- DOM优化
- 回流与重绘
- 未整理
- 文档碎片
- DOM映射机制
- DOM库封装
- 事件
- 功能组件
- table
- 图片延迟加载
- 跑马灯
- 回到顶部
- 选项卡
- 鼠标跟随
- 放大镜
- 搜索
- 多级菜单
- 拖拽
- 瀑布流
- 数据类型的核心操作原理
- 变量提升
- 闭包(scope)
- this
- 练习题
- 各种数据类型下的常用方法
- JSON
- 数组
- object
- oop
- 单例模式
- 高级单例模式
- JS中常用的内置类
- 基于面向对象创建数据值
- 原型和原型链
- 可枚举和不可枚举
- Object.create
- 继承的六种方式
- ES6下一代js标准
- babel
- 箭头函数
- 对象
- es6勉强笔记
- 流程控制
- switch
- Ajax
- eval和()括号表达式
- 异常信息捕获
- 逻辑与和或以及前后自增
- JS中的异步编程思想
- 上云
- 优化技巧
- 跨域与JSONP
- 其它跨域相关问题
- console
- HTML、XHTML、XML
- jQuery
- zepto
- 方法重写和方法重载
- 移动端
- 响应式布局开发基础
- 项目一:创意简历