HTMLCollection vs. NodeList
本文章著作權歸飢人谷_Lyndon和飢人谷所有,轉載請註明出處
>>> 引文
這篇部落格起源於我對一道作業題的思考,在DOM課程中,第二道作業題是:
elem.children
和elem.childNodes
的區別?
那麼這兩者的區別究竟是什麼呢?當時我在回答的時候寫了這樣一段程式碼(這段程式碼只得到表面上的答案,是淺層次理解)。
<div id="ct">
<p class="para">Lyndon</p>
<p class="attr">123<span>dozz</span></p>
</div>
<script>
var ct = document.getElementById("ct");
console.log(ct.children);
console.log(ct.childNodes);
</script>
返回的結果是:
可以看出,當我用getElementById
方法匹配到id = "ct"
的元素節點後
- 用
ct.children
返回的是一個HTMLCollection
(圖中已用紅框標出),其中包含的兩個元素是p.para
以及p.attr
- 用
ct.childNodes
返回的是一個NodeList
(圖中已用紅框標出),其中包含的元素稍微多些,有5項:text
,p.para
,text
,p.attr
,text
每一個元素不斷展開,會發現有很多的屬性,零零碎碎的,這時候我發現一個比較明顯的區別是textContent
的不同:
- 在
HTMLCollection
下-
p.para
的textContent
是"Lyndon"
-
p.attr
的textContent
是"123dozz"
-
- 在
NodeList
下-
text
的textContent
是"↵ "
-
p.para
的textContent
是"Lyndon"
-
text
的textContent
是"↵ "
-
p.attr
的textContent
是"123dozz"
-
text
的textContent
是"↵ "
-
究竟為何兩個方法會返回不一樣的結果?老師的課件歸納如下:
兩者的不同點在於:
-
HTMLCollection
物件具有namedItem()方法,可以傳遞id或name獲得元素; -
HTMLCollection
的item()方法和通過屬性獲取元素(document.forms.f1)可以支援id和name,而NodeList
物件只支援id
但是我並沒有完全看懂,大概掌握程度是0.6左右,於是我覺得解決這些疑惑的終極方法,應該是去深入瞭解:HTMLCollection
和NodeList
本質上的不同。
>>> 首先,參考stack overflow上的回答
我翻譯了一下Vote數最高的答案:
HTMLCollection
與NodeList
都是DOM節點的集合,兩者都屬於Collections範疇,兩者的區別在於:
-
方法略有差異:
HTMLCollection
比NodeList
多了一個namedItem
方法,其他方法保持一致 -
包含節點型別不同:
NodeList
可以包含任何節點型別,HTMLCollection
只包含元素節點(ElementNode)
Collections的出現場景?
- 當返回多個節點(如:
getElementByTagName
)或者得到所有子元素(如:element.childNodes
)時,Collections就會出現,這時候就有可能返回HTMLCollection
或者NodeList
>>> 其次參考W3的文件(MDN上也有詳細解釋):
HTMLCollection
是以節點為元素的列表,可以憑藉索引、節點名稱、節點屬性來對獨立的節點進行訪問。HTML DOM中的Collections是實時變動的,當原始檔案變化,Collections也會隨之發生變化。
- 屬性:
length
(返回的是列表的長度) - 方法1:
item
(通過序號索引來獲取節點,引數是索引值,超過索引值返回null)
<div id="ct">
<p class="para">Lyndon</p>
<p class="attr">123<span>dozz</span></p>
<form action="" method="get" name="apply">
<input type="text" name="username" placeholder="使用者名稱">
<input type="password" name="password" placeholder="密碼">
</form>
</div>
<script>
var ct = document.getElementById("ct");
var a = ct.children;
var b = ct.childNodes;
console.log(a);
console.log(b);
</script>
- 方法2:
namedItem
(用名字來返回一個節點,首先搜尋是否有匹配的id屬性,如果沒有就尋找是否有匹配的name屬性,如果都沒有,返回null)
<div id="ct">
<p class="para">Lyndon</p>
<p class="attr">123<span>dozz</span></p>
<form action="" method="get" name="apply">
<input type="text" name="username" placeholder="使用者名稱">
<input type="password" name="password" placeholder="密碼">
</form>
</div>
<script>
var ct = document.getElementById("ct");
var a = ct.children;
var b = ct.childNodes;
console.log(a);
console.log(b);
</script>
NodeList
返回節點的有序集合,DOM中的NodeList
也是實時變動的
- 屬性:
length
(列表中節點的數量) - 方法:
item
(返回集合中的元素,如果超過範圍返回null)
<div id="ct">
<p class="para">Lyndon</p>
<p class="attr">123<span>dozz</span></p>
<form action="" method="get" name="apply">
<input type="text" name="username" placeholder="使用者名稱">
<input type="password" name="password" placeholder="密碼">
</form>
</div>
<script>
var ct = document.getElementById("ct");
var a = ct.children;
var b = ct.childNodes;
console.log(a);
console.log(b);
</script>
>>> Element與Node
到這一步,兩者本質上的區別已經差不多分清楚了,那麼現在就要進入第二個問題,為什麼兩個Element屬性返回的結果(如:textContent
)不一樣呢?這裡需要感謝同班同學 joyside,他推薦給我一篇文章《Element和Node的區別你造嗎?》來理解Element和Node的區別。
文章中參考的是MDN:Node是一個基礎型別,document, element, text, comment, DocumentFragment等都繼承於Node. 在這篇文章最開始的測試中NodeList
結果中有非常多的text
,其實element, text, comment都是Node的子類,可以將它們視為:elementNode, textNode以及commentNode.平時在DOM中最常用的Element物件,其本質就是elementNode.
由於Node就是DOM的結構,程式碼內容經過解析後,Node與Node之間可以插入文字,文章最開頭的截圖中的"↵ "
本質上就是Node之間的空隙,這種空隙的本質是textNode.
>>> 總結
綜上所述,進行歸納,並回答文章開頭提出的疑問。
-
HTMLCollection
和NodeList
的共同點顯而易見:- 都是類陣列物件,都有
length
屬性 - 都有共同的方法:
item
,可以通過item(index)
或者item(id)
來訪問返回結果中的元素 - 都是實時變動的(live),document上的更改會反映到相關物件上(例外:
document.querySelectorAll
返回的NodeList
不是實時的)
- 都是類陣列物件,都有
-
HTMLCollection
和NodeList
的區別是:-
NodeList
可以包含任何節點型別,HTMLCollection
只包含元素節點(elementNode),elementNode就是HTML中的標籤 -
HTMLCollection
比NodeList
多一項方法:namedItem
,可以通過傳遞id或name屬性來獲取節點資訊
-
文章開頭的疑問解答:
文章開頭的程式碼實際上等價於:
這裡是介於node與node之間的textNode
<div id="ct">
這裡是介於node與node之間的textNode
<p class="para">Lyndon</p>
這裡是介於node與node之間的textNode
<p class="attr">123<span>dozz</span></p>
這裡是介於node與node之間的textNode
</div>
<script>
var ct = document.getElementById("ct");
console.log(ct.children);
console.log(ct.childNodes);
</script>
由於NodeList
包含任何節點型別,ct.childNodes
會一併返回textNode, elementNode等,所以最終結果就是由text
, p
, text
, p
, text
組成的類陣列物件,這裡的text
只是換行符而已。
由於HTMLCollection
僅包含elementNode,因此最終的結果就是由p.para
, p.attr
組成的類陣列物件。當然,由於這裡只返回直接的子元素,因此不會出現類陣列物件中沒有span
,如果希望返回結果中有span
,這樣寫就可以了:
<div id="ct">
<p class="para">Lyndon</p>
<p class="attr">
<span>dozz</span>
</p>
<span>bilibili</span>
</div>
<script>
var ct = document.getElementById("ct");
console.log(ct.children);
console.log(ct.childNodes);
老師在課件中還詳細給出了有哪些具體的方法可以獲取HTMLCollection
和NodeList
物件,如果要記住可能比較麻煩,每次在具體情況時參考控制檯的輸出,得知型別後只需要記住常用的方法和區別就可以輕鬆地進行操作了。
>>> 參考資料
相關文章
- HTMLCollection與NodeListHTML
- NodeList,NamedNodeMap和HTMLCollectionHTML
- javascript中的動態集合NodeList&HTMLCollectionJavaScriptHTML
- js便籤筆記(1)——說說HTMLCollection、NodeList以及NamedNodeMapJS筆記HTML
- HTML5標籤HTMLCollection和NodeList的區別詳解HTML
- Airflow vs. Luigi vs. Argo vs. MLFlow vs. KubeFlowAIUIGo
- MVC vs. MVP vs. MVVMMVCMVPMVVM
- js查詢HTMLCollection物件中的下標JSHTML物件
- git revert .vs. git reset .vs. git rebaseGit
- String.format VS. StrSubstitutor VS. NamedParameterJdbcTemplateORMJDBC
- 搞懂:資料科學vs.機器學習vs.資料分析vs.商業分析資料科學機器學習
- PostgreSQL vs. MySQLMySql
- AutoIt vs. QTPQT
- 拋棄臃腫的 jQuery,用 NodeList.js 操作 DOMjQueryJS
- 【譯】GraphQL vs. RESTREST
- JavaScript運算子:== VS. ===JavaScript
- Accoona VS. GoogleGo
- Ansible vs. TerraformORM
- 大資料檔案格式比較:AVRO vs. PARQUET vs. ORC大資料VR
- Java 下的 JSON庫效能比較:JSON.simple vs. GSON vs. Jackson vs. JSONPJavaJSON
- Git branching: master vs. origin/master vs. remotes/origin/masterGitASTREM
- 柏拉圖洞穴寓言 vs. 表徵假說 vs. 表觀遺傳
- Spring WebClient vs. RestTemplateSpringWebclientREST
- Redis vs. MongoDB比較RedisMongoDB
- 引用計數 vs. GCGC
- javascript requestAnimationFrame vs. setTimeoutJavaScriptrequestAnimationFrame
- HTML 5 Canvas vs. SVGHTMLCanvasSVG
- PostgreSQL vs. Oracle 測試SQLOracle
- WebForms VS. MVC(翻譯)WebORMMVC
- PostgreSQL vs. MS SQL ServerSQLServer
- Angular vs. React - the tie breakerAngularReact
- JavaScript構建(編繹)系統大比拼:Grunt vs. Gulp vs. NPMJavaScriptNPM
- Quarkus vs. SpringBoot - RedditSpring Boot
- Ruby on Rails Mountable vs. Full EngineAI
- 語言戰爭: PHP vs. RubyPHP
- URL vs. HTML 錄製模式HTML模式
- 轉貼:Spring vs. EJBSpring
- HTML 5 vs. 本地應用HTML