DOM 的集合 (collection) 不等於陣列 (array)
阿恆
初學 DOM 的人很容易把節點集合(collection of nodes)與節點陣列(arrray of nodes)混淆,並且把節點集合當作陣列來使用,結果鬧出不少問題,浪費很多除錯的時間。James Edwards 有一篇文章介紹這兩者的分別,並且說明如何把節點集合轉換為節點陣列。DOM 有很多內建的 method 送回節點集合,所以釐清這兩個概念非常重要。
節點集合的官方名稱是 NodeList,根據 W3C 的 DOM level 3 核心文件,送回 NodeList 的 methods 包括 Document.getElementByTagName()、Node.childNodes 等,歷遍 NodeList 的方法跟歷遍陣列差不多:
|
|
但你不能使用陣列專用的 methods 包括 push()、splice()、reverse() 等來處理 NodeList。
有需要的話,你可以用以下的方法把 NodeList 轉換成陣列,這真的十分簡單:
|
|
以上代碼可以在任何瀏覽器上執行,調用的時候只需輸入要轉換的 NodeList:
|
|
若果你的瀏覽器支援原生物件原型(native object prototyping),例如 Opera、Firefox、Safari 3,你可以為 NodeList 加入一個 toArray() method:
|
|
這樣便可以把它當作 NodeList 的內建 mothod 直接調用。
不論你如何進行轉換,它都有一個顯而易見的缺點,就是得到的結果不再是一個 NodeList,即是說:
- 轉換後的陣列喪失了繼承自 NodeList 的屬性和 method,其實 NodeList 只有一個屬性(就是 length,陣列也有這個屬性),和一個 method(就是 item(),不過它通常是多餘的,因為我們可以使用方括號表達法),所以這方面的損失很有限。
- 這不再是一個「活」的集合,實作上 NodeList 是物件參考的集合,如果集合改變(例如成員元素的增加或刪減),它會自動更新以反映這種變化,相反陣列是一個靜態的結構,只代表集合在某特定時間的快照,所以不會隨著 DOM 的變化而更新。視乎你的具體情況,這些變化可以相當大。
- array
- arrray of nodes
- childNodes
- collection
- collection of nodes
- DOM
- getElementByTagName
- native object prototyping
- 分別
- 原生物件原型
- 歷遍陣列
- 節點陣列
- 節點集合