[toc]
>以下內容基本整理自[大漠のJavaScript學習筆記:動態集合](https://www.w3cplus.com/javascript/dom-dynamic-collection.html)
## 樹狀圖
### 從原型鏈看

### 從節點包含看


## 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);
```

#### 獲取NodeList集合的方法二:`querySelector`
```
let divs = document.querySelectorAll('div') ;
console.log(divs, divs.length);
console.log(divs instanceof NodeList);
```

#### 遍歷NodeList
NodeList可以通過`[]表達式`來訪問,也可以通過`item()`方法來訪問。而且它也有length屬性,可以訪問元素個數。雖然JavaScript中的數組可以修改length屬性,但NodeList是一個類數組,而且它是頁面一片區域的DOM結構映射。所以不要修改NodeList對象的length值。

#### 兩者獲取到的NodeList的區別
Node的childNodes和document.querySelectAll()對應的NodeList是有所不同的,前者是`動態的`,后者是`靜態的`。

### 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)
```

#### 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
- 方法重寫和方法重載
- 移動端
- 響應式布局開發基礎
- 項目一:創意簡歷