NodeList,NamedNodeMap和HTMLCollection

廿四橋明月夜發表於2017-10-06

DOM是JavaScript重要組成部分,在DOM中有三個特別的集合分別是NodeList(節點的集合),NamedNodeMap(元素屬性的集合)和HTMLCollection(html元素的集合)。這三個集合有一些共同的特點:它們都可以通過中括號表示式來訪問集合中元素,也有length屬性。但它們並不是陣列,而且它們都是動態的,會根據頁面元素的變化而變化。下面就來介紹一下它們。

NodeList集合

1.如何獲取NodeList集合

  DOM將HTML頁面解析成一個由多層次節點構成的結構。節點是頁面結構的基礎,而所有節點繼承自Node型別,因此所有節點共享著基本的屬性和方法。Node型別有一個childNodes屬性,所以所有節點都擁有這個屬性。而通過這個屬性就可以得到一個儲存著本節點的子節點組成的NodeList物件。

2.如何操作NodeList

  NodeList可以通過方括號表示式來訪問,也可以通過item()方法來訪問。”他“也有length屬性,可以訪問元素個數。雖然javascript中的陣列可以修改length屬性。但NodeList集合並不是陣列,而且它是頁面一片區域的DOM結構對映。所以請不要修改NodeList物件的length值。

var firstChild = someNode.childNodes[0];//獲取第一個元素
var secondChild = someNode.childNodes.item(1);//獲取第二個元素
var count = someNode.childNodes.length;//獲取集合長度
  • 1
  • 2
  • 3

NamedNodeMap

1.如何獲取NamedNodeMap

  Element型別這種DOM節點是唯一擁有attributes屬性的一種節點型別。而attribute屬性中就包含NamedNodeMap集合。它由元素的特性組成。所以只要是元素節點,呼叫attributes屬性就可以得到NamedNodeMap集合。

2.如何操作NamedNodeMap集合

  NamedNodeMap集合的元素擁有nodeName和nodeValue屬性,分別表示元素特性名稱和特性值,也擁有以下方法: 
1>getNamedItem(name);返回nodeName屬性等於name的節點; 
2>removeNamedItem(name);從列表中移除nodeName節點; 
3>setNamedItem(node);向列表中新增節點,以節點nodeName為屬性索引; 
4>item(pos);返回位於數字pos位置的節點。

var className = element.attributes.getNamedItem('class').nodeValue;
var className1 = element.attributes['class'].nodeValue;
var oldAttr = element.attributes.removeNamedItem('class');
  • 1
  • 2
  • 3

  一般元素節點的getAttribute()、removeAttribute()和setAttribute()方法都可以完成以上操作。

HTMLCollection

1.如何得到HTMLCollection集合

  HTMLCollection是元素節點的集合可以通過getElementsByTagName()方法(獲取同型別的元素)、getElementsByName()方法(獲取name特性相同的元素)、document的anchors屬性(包含name特性的a元素),forms屬性(包含文件所有form元素),images屬性(包含文件所有img元素),links屬性(文件所有帶href特性的a元素)。

2.與NodeList區別

  HTMLCollection集合操作方法和NodeList集合操作的方法相同,就不再重複了。這兩個集合的區別是HTMLColletion中只有元素節點(nodeType=1),而NodeList集合可以擁有元素節點,文字節點(nodeType=3),註釋節點(nodeTypd=8)等。

注意事項

  這三個集合都是“動態的”;當文件結構發生變化時,它們都會更新,所以以下操作就會發生錯誤:

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
    var div = document.createElement('div');
    document.body.appendChild(div);
}
  • 1
  • 2
  • 3
  • 4
  • 5

   以上程式碼中的for迴圈將會一直執行,因為div得到的HTMLCollection集合是動態的,當每次給body新增元素divs都會進行更新,所以會一直迴圈下去。

解決方法1:將初始的集合的length存起來

var divs = document.getElementsByTagName('div');
for (var i = 0, var len = divs.length; i < len; i++) {
    var div = document.createElement('div');
    document.body.appendChild(div);
}
  • 1
  • 2
  • 3
  • 4
  • 5

解決方法2:將以上集合轉化為陣列

var divs = document.getElementsByTagName('div');
//將HTMLCollection轉換為陣列(此方法在IE8及以前不能用)
var divsArr = Array.prototype.slice.call(divs,0);
for (var i = 0; i < divsArr.length; i++) {
    var div = document.createElement('div');
    document.body.appendChild(div);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

將以上集合轉為陣列的方法(通用):

function convertListToArray(nodes) {
   var array = null;
   try{//標準瀏覽器
       array = Array.prototype.slice.call(nodes,0);
   }catch(ex){//IE8及以下遍歷每一項分別新增到陣列中
       array = new Array();
       for(var i = 0,len = nodes.length;i < len;i++){
           array.push(nodes[i]);
       }
   }
   return array;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

  以上就是我對NodeList,NamedNodeMap和HTMLCollection集合的簡單介紹,如有問題希望提出,感謝看到最後。


相關文章