# NodeList 接口,HTMLCollection 接口
節點都是單個對象,有時需要一種數據結構,能夠容納多個節點。DOM 提供兩種節點集合,用于容納多個節點:`NodeList`和`HTMLCollection`。
這兩種集合都屬于接口規范。許多 DOM 屬性和方法,返回的結果是`NodeList`實例或`HTMLCollection`實例。主要區別是,`NodeList`可以包含各種類型的節點,`HTMLCollection`只能包含 HTML 元素節點。
## NodeList 接口
### 概述
`NodeList`實例是一個類似數組的對象,它的成員是節點對象。通過以下方法可以得到`NodeList`實例。
- `Node.childNodes`
- `document.querySelectorAll()`等節點搜索方法
```javascript
document.body.childNodes instanceof NodeList // true
```
`NodeList`實例很像數組,可以使用`length`屬性和`forEach`方法。但是,它不是數組,不能使用`pop`或`push`之類數組特有的方法。
```javascript
var children = document.body.childNodes;
Array.isArray(children) // false
children.length // 34
children.forEach(console.log)
```
上面代碼中,NodeList 實例`children`不是數組,但是具有`length`屬性和`forEach`方法。
如果`NodeList`實例要使用數組方法,可以將其轉為真正的數組。
```javascript
var children = document.body.childNodes;
var nodeArr = Array.prototype.slice.call(children);
```
除了使用`forEach`方法遍歷 NodeList 實例,還可以使用`for`循環。
```javascript
var children = document.body.childNodes;
for (var i = 0; i < children.length; i++) {
var item = children[i];
}
```
注意,NodeList 實例可能是動態集合,也可能是靜態集合。所謂動態集合就是一個活的集合,DOM 刪除或新增一個相關節點,都會立刻反映在 NodeList 實例。目前,只有`Node.childNodes`返回的是一個動態集合,其他的 NodeList 都是靜態集合。
```javascript
var children = document.body.childNodes;
children.length // 18
document.body.appendChild(document.createElement('p'));
children.length // 19
```
上面代碼中,文檔增加一個子節點,NodeList 實例`children`的`length`屬性就增加了1。
### NodeList.prototype.length
`length`屬性返回 NodeList 實例包含的節點數量。
```javascript
document.querySelectorAll('xxx').length
// 0
```
上面代碼中,`document.querySelectorAll`返回一個 NodeList 集合。對于那些不存在的 HTML 標簽,`length`屬性返回`0`。
### NodeList.prototype.forEach()
`forEach`方法用于遍歷 NodeList 的所有成員。它接受一個回調函數作為參數,每一輪遍歷就執行一次這個回調函數,用法與數組實例的`forEach`方法完全一致。
```javascript
var children = document.body.childNodes;
children.forEach(function f(item, i, list) {
// ...
}, this);
```
上面代碼中,回調函數`f`的三個參數依次是當前成員、位置和當前 NodeList 實例。`forEach`方法的第二個參數,用于綁定回調函數內部的`this`,該參數可省略。
### NodeList.prototype.item()
`item`方法接受一個整數值作為參數,表示成員的位置,返回該位置上的成員。
```javascript
document.body.childNodes.item(0)
```
上面代碼中,`item(0)`返回第一個成員。
如果參數值大于實際長度,或者索引不合法(比如負數),`item`方法返回`null`。如果省略參數,`item`方法會報錯。
所有類似數組的對象,都可以使用方括號運算符取出成員。一般情況下,都是使用方括號運算符,而不使用`item`方法。
```javascript
document.body.childNodes[0]
```
### NodeList.prototype.keys(),NodeList.prototype.values(),NodeList.prototype.entries()
這三個方法都返回一個 ES6 的遍歷器對象,可以通過`for...of`循環遍歷獲取每一個成員的信息。區別在于,`keys()`返回鍵名的遍歷器,`values()`返回鍵值的遍歷器,`entries()`返回的遍歷器同時包含鍵名和鍵值的信息。
```javascript
var children = document.body.childNodes;
for (var key of children.keys()) {
console.log(key);
}
// 0
// 1
// 2
// ...
for (var value of children.values()) {
console.log(value);
}
// #text
// <script>
// ...
for (var entry of children.entries()) {
console.log(entry);
}
// Array [ 0, #text ]
// Array [ 1, <script> ]
// ...
```
## HTMLCollection 接口
### 概述
`HTMLCollection`是一個節點對象的集合,只能包含元素節點(element),不能包含其他類型的節點。它的返回值是一個類似數組的對象,但是與`NodeList`接口不同,`HTMLCollection`沒有`forEach`方法,只能使用`for`循環遍歷。
返回`HTMLCollection`實例的,主要是一些`Document`對象的集合屬性,比如`document.links`、`document.forms`、`document.images`等。
```javascript
document.links instanceof HTMLCollection // true
```
`HTMLCollection`實例都是動態集合,節點的變化會實時反映在集合中。
如果元素節點有`id`或`name`屬性,那么`HTMLCollection`實例上面,可以使用`id`屬性或`name`屬性引用該節點元素。如果沒有對應的節點,則返回`null`。
```javascript
// HTML 代碼如下
// <img id="pic" src="http://example.com/foo.jpg">
var pic = document.getElementById('pic');
document.images.pic === pic // true
```
上面代碼中,`document.images`是一個`HTMLCollection`實例,可以通過`<img>`元素的`id`屬性值,從`HTMLCollection`實例上取到這個元素。
### HTMLCollection.prototype.length
`length`屬性返回`HTMLCollection`實例包含的成員數量。
```javascript
document.links.length // 18
```
### HTMLCollection.prototype.item()
`item`方法接受一個整數值作為參數,表示成員的位置,返回該位置上的成員。
```javascript
var c = document.images;
var img0 = c.item(0);
```
上面代碼中,`item(0)`表示返回0號位置的成員。由于方括號運算符也具有同樣作用,而且使用更方便,所以一般情況下,總是使用方括號運算符。
如果參數值超出成員數量或者不合法(比如小于0),那么`item`方法返回`null`。
### HTMLCollection.prototype.namedItem()
`namedItem`方法的參數是一個字符串,表示`id`屬性或`name`屬性的值,返回對應的元素節點。如果沒有對應的節點,則返回`null`。
```javascript
// HTML 代碼如下
// <img id="pic" src="http://example.com/foo.jpg">
var pic = document.getElementById('pic');
document.images.namedItem('pic') === pic // true
```
- 前言
- 入門篇
- 導論
- 歷史
- 基本語法
- 數據類型
- 概述
- null,undefined 和布爾值
- 數值
- 字符串
- 對象
- 函數
- 數組
- 運算符
- 算術運算符
- 比較運算符
- 布爾運算符
- 二進制位運算符
- 其他運算符,運算順序
- 語法專題
- 數據類型的轉換
- 錯誤處理機制
- 編程風格
- console 對象與控制臺
- 標準庫
- Object 對象
- 屬性描述對象
- Array 對象
- 包裝對象
- Boolean 對象
- Number 對象
- String 對象
- Math 對象
- Date 對象
- RegExp 對象
- JSON 對象
- 面向對象編程
- 實例對象與 new 命令
- this 關鍵字
- 對象的繼承
- Object 對象的相關方法
- 嚴格模式
- 異步操作
- 概述
- 定時器
- Promise 對象
- DOM
- 概述
- Node 接口
- NodeList 接口,HTMLCollection 接口
- ParentNode 接口,ChildNode 接口
- Document 節點
- Element 節點
- 屬性的操作
- Text 節點和 DocumentFragment 節點
- CSS 操作
- Mutation Observer API
- 事件
- EventTarget 接口
- 事件模型
- Event 對象
- 鼠標事件
- 鍵盤事件
- 進度事件
- 表單事件
- 觸摸事件
- 拖拉事件
- 其他常見事件
- GlobalEventHandlers 接口
- 瀏覽器模型
- 瀏覽器模型概述
- window 對象
- Navigator 對象,Screen 對象
- Cookie
- XMLHttpRequest 對象
- 同源限制
- CORS 通信
- Storage 接口
- History 對象
- Location 對象,URL 對象,URLSearchParams 對象
- ArrayBuffer 對象,Blob 對象
- File 對象,FileList 對象,FileReader 對象
- 表單,FormData 對象
- IndexedDB API
- Web Worker
- 附錄:網頁元素接口
- a
- img
- form
- input
- button
- option
- video,audio