主要有兩個方面不同
1.包含節點的類型
2.使用方法html
1.包含節點的類型不一樣(重要)node
(1)NodeList 一個節點的集合,既能夠包含元素和其餘節點(註釋節點、文本節點等)。 (2)HTMLCollection 元素集合, 只有Element
2.使用方法chrome
相同點: 1) 它們都有length屬性 2) 都有元素的getter,叫作item,能夠傳入索引值取得元素。 3) 都是類數組 不一樣點: HTMLCollection還有一個nameItem()方法,能夠返回集合中name屬性和id屬性值的元素。(部分瀏覽器也支持NodeList的nameItem()方法)
涉及獲取元素的主要API
DOM最初設計是爲了解析XML而設計的,以後沿用到HTML上。咱們能夠把DOM分爲兩部分 core 和 html,Core 部分提供最基礎的 XML 解析API說明,HTML 部分專爲 HTML 中的 DOM 解析添加其特有的 API。NodeList接口是在core中體現的,HTMLCollection則是在html部分,不一樣瀏覽器也會實現它們的不一樣接口。可是如今的dom標準已經不分core和html了,反映的是瀏覽器的實現()。惟一要注意的是 querySelectorAll 返回的雖然是 NodeList ,可是其實是元素集合,而且是靜態的(其餘接口返回的HTMLCollection和NodeList都是live的)。
DOM中的NodeList NamedNodeMap 及 HTMLCollection
把這三個放在一塊兒說,是由於三者都是DOM中的array-like對象,即類數組對象(於是也都具備length屬性)。
(1)先說NamedNodeMap這個對象,這個比較簡單,雖然翻譯過來是 命名的節點映射,但它只不過是 Attr這個對象的一個集合,Attr對象是DOM元素節點的屬性的對象表達。經過元素節點(element node)的attributes屬性返回的就是NamedNodeMap這個對象。與NodeList相同的是它也是一個動態的集合(live collection),與NodeList不一樣的是,NamedNodeMap中保存的是一組無序的屬性節點的集合。
(2)NodeList對象是由childNodes屬性,querySelectorAll方法返回的一組節點的集合,它保存着一組有序的節點。注意區別的是,由childNodes屬性返回的NodeList對象是一個動態的集合(live collection), 而由querySelectorAll方法返回的則是一個靜態的集合(static collection)。於是在MDN中將他定義爲 」A sometimes-live collection「,live collection 指的是對對DOM的操做引發的的變化會實時的反映在這個集合裏。
(3)接下來就是HTMLCollection,它在本質是一個動態的NodeList對象。getElementsByTagName等方法返回的是包含零或多個元素的NodeList,在HTML文檔中,返回的則是HTMLCollection對象。所以說它在本質上一個NodeList對象,包含一組有序(in document order基於文檔結構順序)的動態集合。數組
在獲取原生DOM元素的時候,主要涉及這幾個DOM API(連接爲Living Standard):瀏覽器
• Node及對應集合NodeList • Element(繼承Node)及對應集合HTMLCollection • Document(繼承Node)
注:計劃取代NodeList和HTMLCollection的Elements目前並沒有普遍實現app
基礎知識 -- NodeList v.s. HTMLCollection
使用Node Interface的方法,如childNodes,獲得的一般是NodeList,而使用其餘Interface的方法,又有可能獲得HTMLCollection。因此有必要了解一下這二者的區別。
關於這兩個類型的差別,在Stackoverflow上有一個不錯的問答。
其實,只要先看看Living Standard中這兩個類型的IDL,便能猜出大概了。NodeList的IDL以下:dom
interface NodeList { getter Node? item(unsigned long index); readonly attribute unsigned long length; iterable<Node>; };
而HTMLCollection的IDL以下:spa
interface HTMLCollection { readonly attribute unsigned long length; getter Element? item(unsigned long index); getter Element? namedItem(DOMString name); };
相同點:
4) 都是類數組對象
5) 它們都有length屬性
6)都有元素的getter,叫作item
不一樣點:
1.NodeList的元素是Node,HTMLCollection的元素是Element。prototype
Element繼承自Node,是Node的一種,在HTML中,它通常是HTML元素(好比<p>之類的標籤建立出來的對象)。而Node做爲父類,除了Element還有一些其餘子類,好比HTML元素內的文本對應的Text,文檔對應的Document,註釋對應的Comment。HTMLCollection裏,只有Element,而NodeList裏能夠有Element、Text、Comment等多種元素。按說若是獲取元素返回的列表裏只有Element,那這兩種類沒多大區別,但事實上不少時候瀏覽器會將解析HTML文本時獲得的Text和Comment一併放進列表裏放回。好比說下面這一段代碼翻譯
<div> <!-- Comment --> <p>This is Some Text</p> </div>
若將這個div的子元素放在列表裏返回,那麼若是是做爲NodeList返回,瀏覽器最多能夠給這個列表5個元素(不一樣瀏覽器可能不一樣)
1. 一個<div>和註釋間的斷行和空格(或tab)做爲text node(沒錯,標籤之間的空白符號也能夠被解析爲text node) 2. 註釋做爲comment node 3. 註釋和<p>之間的斷行和空格(或tab)做爲text node 4. p做爲element 5. </p>和</div>之間的斷行和空格(或tab)做爲text node
所以NodeList裏可能會有不少通常DOM操做不須要的text node和comment node須要處理。而HTMLCollection則簡單多了,只有<p>這一個元素,這也是比較符合大多數人直覺的結果。
2.HTMLCollection還有一個namedItem方法,能夠快速獲取其中元素。假設有這樣一段HTML:
<div> <!-- Comment --> <p>This is Some Text</p> <img name="test" src="test.jpg"> </div>
那麼假設獲得了這個div的子元素構成的HTMLCollection,叫作list,那麼使用list.namedItem("test")就能夠直接獲得裏面的img元素。
查找順序參考Living Standard,可是在現實中不是全部瀏覽器都遵循標準。好比標準規定若是有多個擁有相同id或者name的元素,只要返回第一個,但chrome和opera會將它們放在一個HTMLCollection或者NodeList裏一併返回,參見MDN。
從IDL看不出來的還有以下幾點
1. 這兩個類都是「live」的。對其中元素進行操做,會實時反映到DOM中(也所以若是一次性直接在這類列表上進行多個DOM操做的話,帶來的開銷會很大)。 2. item和namedItem均可以經過[]的縮寫進行調用,有的瀏覽器還支持用()的縮寫進行調用(也就是能夠list[index],list[key]或者list(index),list(key)),以及直接用dot notation調用namedItem(好比list.key)。 3. 部分瀏覽器支持對NodeList調用namedItem或間接經過[]、()、dot notation來調用namedItem,但因爲各瀏覽器支持不一樣,最好不對NodeList作這種操做。 4. IE8及如下版本瀏覽器中,註釋屬於HTMLCommentElement,算做Element,所以會出如今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的實時性很是有用,可是,咱們有時要迭代一個NodeList或HTMLCollection對象的時候,咱們一般會選擇生成當前對象的一個快照或靜態副本:轉換爲數組類型: var staticLists = Array.prototype.slice.call(nodeListorHtmlCollection, 0) 這樣的話,咱們就能夠放心的對當前的DOM集合作一些刪減和插入操做,這個在DOM密集操做的時候頗有用。