DOM中的NodeList與HTMLCollection


  最近在看《Javascript高級程序設計》的時候,看到了這樣一句話:“理解NodeList和HTMLCollection,是從整體上透徹理解DOM的關鍵所在。”,所以覺得應該寫一篇關於NodeList和HTMLCollection的博客來好好了解和總結下這方面的知識點。

     NodeList

  NodeList是一個節點的集合(既可以包含元素和其他節點),在DOM中,節點的類型總共有12種,通過判斷節點的nodeType來判斷節點的類型。

  我們可以通過Node.childNodes和document.querySelectAll() (返回NodeList的接口有很多,這里不一一列舉,下同)來獲取到一個NodeList對象。

  NodeList對象有個length屬性和item()方法,length表示所獲得的NodeList對象的節點個數,這里還是要強調的是節點,而item()可以傳入一個索引來訪問Nodelist中相應索引的元素。

 1 <body>
 2     <div id="node">
 3         文本節點
 4         <!-- 注釋節點 -->
 5         <span>node1</span>
 6         <span>node2</span>
 7         <span>node3</span>
 8     </div>
 9 </body>
10 <script>
11     var node = document.getElementById('node'),
12         nodeLists = node.childNodes
13     console.log(nodeLists.length) //     輸出為9
14 </script>

 

  上面的HTML代碼中,“文本節點”和父節點子節點的空格(連着的文本)算做一個文本節點,然后是一個注釋節點和注釋節點和元素節點之間的空格(換行會產生空格,空格算做文本節點)的文本節點,緊接着的是一個元素節點和元素節點之間的換行的文本節點,三個元素節點和元素節點間的兩個文本節點,最后是最后得元素節點和父元素之間的空格產生的文本節點,總共是9個節點。

  NodeList對象的一大特點是它返回的內容是動態的(live),也就是說我們上面代碼獲取nodeLists是類似於“指針”的東西,所以在下面代碼中我們在獲取了nodeLists之后再向node中插入一個創建的span標簽后,發現獲取到了nodeLists.length變為10了,但是querySelectorAll這個接口返回的nodeList對象比較特殊,它是個靜態(static)的對象。而且是元素的集合。

 1 <body>
 2     <div id="node">
 3         文本節點
 4         <!-- 注釋節點 -->
 5         <span>node1</span>
 6         <span>node2</span>
 7         <span>node3</span>
 8     </div>
 9 </body>
10 <script>
11     var node = document.getElementById('node')
12     var nodeLists = node.childNodes
13     var queryNodes = node.querySelectorAll('span')
14     node.appendChild(document.createElement('span'))
15     console.log(nodeLists.length)  // 輸出為10
16     console.log(queryNodes.length)  //輸出為3
17 </script>

  HTMLCollection

  HTMLCollection是元素集合,它和NodeList很像,有length屬性來表示HTMLCollection對象的長度,也可以通過elements.item()傳入元素索引來訪問。當時它還有一個nameItem()方法,可以返回集合中name屬性和id屬性值得元素。HTMLDocument 接口的許多屬性都是 HTMLCollection 對象,它提供了訪問諸如表單、圖像和鏈接等文檔元素的便捷方式,比如document.images和document.forms的屬性都是HTMLCollection對象。

 1 <body>
 2     <img src="test.png" id="image1">
 3     <img src="test.png" id="image2">
 4     <img src="test.png" id="image3">
 5     <img src="test.png" id="image4">
 6     <img src="test.png" id="image5">
 7     <img src="test.png" id="image6">
 8 </body>
 9 <script>
10     console.log(document.images.namedItem('image1')) //<img src="test.png" id="image1">
11 </script>

  HTMLCollection的集合和NodeList對象一樣也是動態的,他們獲取的都是節點或元素集合的一個引用。

  HTMLCollection和NodeList 實時性

  前面都說到了它們連個對象都不是歷史文檔狀態的一個靜態快照,而是實時性的,這個是一個非常令人驚訝的特性,它們能隨着文檔的改變而改變,這個是很值得我們注意的,我們在平常使用一些DOM 接口來返回一些DOM集合的時候,常常會忽視掉這些。

  HTMLCollection和NodeList的實時性非常有用,但是,我們有時要迭代一個NodeList或HTMLCollection對象的時候,我們通常會選擇生成當前對象的一個快照或靜態副本:

  

1 var staticLists = Array.prototype.slice.call(nodeListorHtmlCollection, 0)

  這樣的話,我們就可以放心的對當前的DOM集合做一些刪減和插入操作,這個在DOM密集操作的時候很有用。

  還有MDN上面提到了一個將NodeList轉化為Array的DOM擴展原型的方法(在IE6/7中存在危險:http://perfectionkills.com/whats-wrong-with-extending-the-dom/):

var arrayMethods = Object.getOwnPropertyNames( Array.prototype );
arrayMethods.forEach( attachArrayMethodsToNodeList );
function attachArrayMethodsToNodeList(methodName)
{
  if(methodName !== "length") {
    NodeList.prototype[methodName] = Array.prototype[methodName];
  }
};
var divs = document.getElementsByTagName( 'div' );
var firstDiv = divs[ 0 ];
firstDiv.childNodes.forEach(function( divChild ){
  divChild.parentNode.style.color = '#0F0';
});

  結語

  DOM最初設計是為了解析XML而設計的,之后沿用到HTML上。我們可以把DOM分為兩部分 core 和 html,Core 部分提供最基礎的 XML 解析API說明,HTML 部分專為 HTML 中的 DOM 解析添加其特有的 API。NodeList接口是在core中體現的,HTMLCollection則是在html部分,不同瀏覽器也會實現它們的不同接口,廠商聯盟性質的規范組織出現會讓這些更加規范,也不出現之前返回的是NodeList對象,但是卻是靜態的。

  這篇文章很多思想都是自己在平時和網上了一些博客中了解到了,其中加了很多自己的組織和理解,目的在於梳理下一些比較深入的知識點,如果寫的有疏漏和錯誤之處,還請指出。

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM