你可能沒有據說過 js中的 DOM操做還有這個: HTMLCollection 和 NodeList

這是我參與 8 月更文挑戰的第 9 天,活動詳情查看: 8月更文挑戰javascript

⛱️序言

猶記得上回有一次面試的時候被問到 htmlCollection 和數組的關係。當時的我內心想的是, html 中的集合和數組的關係,那解題就是說 set 和數組的關係?html

因而……面試官當下當即糾正我, htmlCollection 是單詞連在一塊兒的,是 js 的一個內容。當時我多是想……找個地洞鑽……java

懵逼

不會的咋仍是得虛心接收,查漏補缺仍是比較合理。通過一系列的資料查詢和總結以後,得出如下總結。node

下面開始進入本文的講解~🙋面試

🎈1、基礎知識

1. 定義

(1)HTMLCollection

  • HTMLCollection 表示一個包含了元素(元素順序爲文檔流中的接口)的集合(通用集合),還提供了從該集合中選擇元素的屬性和方法。
  • 例如使用 getElementsByTagName() 方法返回的就是一個 HTMLCollection 對象。

(2)NodeList

  • NodeList 對象是節點的集合。數組

  • 經過如下方法,能夠獲取到 NodeList 對象。主要有:在一些舊版本瀏覽器中的方法,好比 getElementsClassName() 方法,返回的是 NodeList 對象,而不是 HTMLCollection 對象。全部瀏覽器的 Node.childNodes 屬性返回的都是 NodeList 對象。大部分瀏覽器的 document.querySelectorAll() 返回的是 NodeList 對象。瀏覽器

  • 咱們能夠經過如下代碼進行驗證:markdown

    document.body.childNodes instanceof NodeList // true
    document.querySelector('body') instanceof NodeList // true or false
    document.getElementByClassName('body') instanceof NodeList // true or false
    複製代碼

2. 屬性和方法

(1)HTMLCollection

HTMLCollection 對象中的屬性和方法,舉例兩個:app

  • item(index) —— 返回 HTMLCollection指定索引的元素,若是不存在則返回 null
  • length (只讀) —— 返回 HTMLCollection 中元素的數量

接下來用一個例子來進行闡述驗證。具體代碼以下:函數

document.getElementsByTagName('body') instanceof HTMLCollection // true

const htmlCollection = document.getElementsByTagName('body')
console.log(htmlCollection.item(0)) // <body>...</body>
console.log(htmlCollection.length()) // 1
複製代碼

(2)NodeList

NodeList 對象中的屬性和方法主要有如下幾種。包括:

  • item() —— 返回某個元素基於文檔數的索引;
  • length() —— 返回 NodeList 中的節點數量;
  • NodeList.forEach() —— 該方法用於遍歷 NodeList 中的全部成員。它接收一個回調函數做爲參數,每遍歷一回就要執行這個回調函數一次,用法與數組實例的 forEach 方法是徹底一致的;
  • NodeList.keys()/values()/entries() —— 對於這三個方法來講,它們都會返回一個 ES6遍歷器對象,能夠經過 for…of… 來進行循環遍歷,以便於獲取每個成員的信息

同時,須要注意以上三者的區別,分別以下:

  • keys() —— 指的是返回鍵名的遍歷器;
  • values() —— 指的是返回鍵值的遍歷器;
  • entries() —— 指的是返回的遍歷器要同時包含鍵名和鍵值的信息。

咱們寫點代碼來論證以上內容。具體代碼以下:

const nodelist = document.querySelectorAll('body')

console.log(nodelist.item(0)) // <body>...</body>
console.log(nodelist.length) // 1
console.log(nodelist.forEach(item => console.log(item))) // <body>...</body>

for(var key of nodelist.keys()) {
  console.log(nodelist[key]) // <body>...</body>
}

for(var value of nodelist.values()) {
  console.log(value) // <body>...</body>
}

for(var entry of nodelist.entries()) {
  console.log(entry) // [0, body]
}
複製代碼

🪁2、異同點

1. HTMLCollection 與 NodeList 的區別

HTMLCollection NodeList
集合 元素的集合 節點的集合
靜態和動態 HTMLCollection 是動態綁定的,是一個動態集合。DOM 樹發生變化,HTMLCollection 也會隨之變化,說明其節點的增刪是敏感的 NodeList 是一個靜態集合,其不受 DOM 樹元素變化的影響;至關因而 DOM 樹、節點數量和類型的快照,也就是說對節點進行增刪操做時,NodeList 是感受不到的。可是對節點內部內容修改,是能夠感受獲得的,好比修改 innerHTML
節點 不包含屬性節點和文本節點 只有 NodeList 對象有包含屬性節點文本節點
元素獲取方式 HTMLCollection 元素能夠經過 name,id 或 index 索引來獲取 NodeList 只能經過 index 索引來獲取
僞數組 HTMLCollection 和 NodeList 都是類數組,不是數組,只是長得像數組而已。因此沒法使用數組的方法,好比: pop(),push(),或 join() 等等 與 HTMLCollection 同樣

2. querySelectorAll 和 getElementsByTagName 的區別

在上述的表格中咱們能夠了解到, HTMLCollection 是動態集合,當 DOM 樹發生變化時, HTMLCollection 也會隨之改變。而 NodeList 是靜態集合,當 DOM 樹發生變化時, NodeList 不會受到 DOM 樹變化的影響。咱們來舉兩個例子進行闡述說明。

(1)querySelectorAll

先附上代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>htmlCollection和NodeList</title>
</head>
<body>
    <ul>
        <li></li>
        <li></li>
        <li>MondayLab</li>
        <li></li>
        <li></li>
    </ul>
    <script> var oldUl = document.querySelectorAll('ul')[0]; var oldLi = document.querySelectorAll('li'); console.log(oldUl); // NodeList[body] console.log(oldLi.length); // 5 var newLi = document.createElement('li'); oldUl.appendChild(newLi); console.log(oldLi.length); // 5 var length = oldLi.length - 1; oldLi[length].innerHTML = 'monday'; console.log(oldLi[length].innerHTML); // monday  console.log(oldLi.length); // 5 → 雖然經過innerHTML能夠讀到文本節點的內容,可是長度依舊不變,仍是5 </script>
</body>
</html>
複製代碼

你們能夠看到,使用 querySelectorAll 來獲取 <li> ,返回的是一個 NodeList 的集合。且當頁面 DOM 結構發生改變時,其長度不會發生任何的改變。可是當改變 innerHTML 時,則文本節點的內容會發生改變。值得注意的是,即便 innerHTML 改變 DOM 的結構,但長度依舊是不變的,仍是 5

(2)getElementsByTagName

先附上代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTMLCollection</title>
</head>
<body>
    <ul>
        <li></li>
        <li></li>
        <li>MondayLab</li>
        <li></li>
        <li></li>
    </ul>
    <script> var oldUl = document.getElementsByTagName('ul')[0]; var oldLi = document.getElementsByTagName('li'); console.log(oldUl); // HTMLCollection[body] console.log(oldLi.length); // 5 var newLi = document.createElement('li'); oldUl.appendChild(newLi); console.log(oldLi.length); // 6 → 順利改變 DOM 的結構 </script>
</body>
</html>
複製代碼

你們能夠看到,使用 getElementByTagName 時,獲取的是一個 HTMLCollection 集合,這個時候說明對節點進行增刪操做時,頁面的 DOM 結構會發生改變,且HTMLCollection實時地獲取到集合的長度。

📞3、結束語

寫到這裏的時候,不得不感概 jsDOM 操做是如此的強大,也忽然就明白了本身以前寫代碼的時候爲啥會遇到那麼多坑。若是在學習之初就追溯於原理,可能跳的坑應該就能少不少了。

講到這裏,關於 HTMLCollectionNodeList 的內容就結束啦!但願對你們有幫助~

彩蛋有幾篇我看過還比較好理解的文章,有須要能夠當擴展知識進行擴充哦~

🐣彩蛋 One More Thing

(:參考資料

lio_zero👉HTMLCollection和NodeList的區別

Snandy👉將HTMLCollection/NodeList/僞數組轉換成數組

binyellow👉DOM操做,HTMLCollection、NodeList

愛民👉NodeList 和 HTMLCollection

(:番外篇

  • 關注公衆號星期一研究室,第一時間關注優質文章,更多精選專欄待你解鎖~

  • 若是這篇文章對你有用,記得留個腳印jio再走哦~

  • 以上就是本文的所有內容!咱們下期見!👋👋👋

相關文章
相關標籤/搜索