HTMLCollection 和 Nodelist 的異同? 1. w3 關於這兩者的定義 HTMLCollection: An HTMLCollection is a list of nodes. An individual node may be accessed by either ordin ...
HTMLCollection 和 Nodelist 的異同?
1. w3 關於這兩者的定義
HTMLCollection: An
HTMLCollection
is a list of nodes. An individual node may be accessed by either ordinal index or the node'sname
orid
attributes. Note: Collections in the HTML DOM are assumed to be live meaning that they are automatically updated when the underlying document is changed.NodeList: The
NodeList
interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented.NodeList
objects in the DOM are live.The items in the
NodeList
are accessible via an integral index, starting from 0.
HTMLCollection
和 NodeList
都是元素節點的集合, 前者可以按照索引/節點name
/節點id
屬性訪問。 後者可以按照索引訪問。
1.1 實例屬性
HTMLCollection 和 NodeList 都只有一個實例屬性:
length
: 返回節點集合的長度
1.2 實例方法
HTMLCollection | NodeList |
---|---|
HTMLCollection.item() :傳入元素 index 返回特定的節點 |
NodeList.item() :傳入索引返回特定節點 |
HTMLCollection.namedItem() :傳入節點的 name 屬性,返回特定的節點 |
NodeList.entries() :返回key-value 的迭代器 |
⚠️HTMLCollection 沒有 forEach 方法 | NodeList.forEach() :節點遍歷方法 |
NodeList.keys() :返回NodeList 的所有key值的迭代器,這裡也就是索引 |
|
NodeList.values() 返回NodeList 的所有value值的迭代器,也就四節點本身 |
一些示例:
<body>
<p name="p1" class="para">Lorem, ipsum dolor.</p>
<p name="p2" class="para">Lorem ipsum dolor sit amet.</p>
<p name="p3" class="para">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</body>
<script>
const paras = document.getElementsByClassName('para');
console.log(paras.item(0).innerHTML);//Lorem, ipsum dolor.
console.log(paras.namedItem('p3').innerHTML);//Lorem ipsum dolor sit amet, consectetur adipisicing elit.
</script>
<body>
<p name="p1" class="para">Lorem, ipsum dolor.</p>
<p name="p2" class="para">Lorem ipsum dolor sit amet.</p>
<p name="p3" class="para">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</body>
<script>
const paras = document.querySelectorAll('.para');
console.log('log1:', paras.item(0).innerHTML);
console.log('log2:', paras.entries());
console.log('log3:', paras.entries().next());
console.log('log4:', paras.keys());
console.log('log5:', paras.keys().next());
console.log('log6:', paras.values());
console.log('log7:', paras.values().next());
paras.forEach((p) => {
console.log('[p.innerHTML]: ', p.innerHTML);
});
</script>
特別說明,在實例方法中,
NodeList/HTMLCollection.item()
方法僅接受索引值。
2. 哪些常見操作會返回這二者?
HTMLCollection
-
document.getElementsByTagName
-
document.getElementsByClassName
-
HTMLElement.children
-
document.forms
-
document.images
NodeList:
document.getElementsByName
document.querySelectorAll
HTMLElement.childNodes
3. 二者有什麼相同點?
二者所包含的結點都是響應式的,也就是說,當所依賴的文檔發生了變化,相應的DOM視圖也會發生更新。
NodeList
為了驗證這一點,我們可以使用 Array.from
(淺拷貝來測試一下):
<script>
const paras = document.querySelectorAll('.para');
const copy = Array.from(paras);
copy.forEach((cp) => {
cp.innerHTML += new Date().toLocaleTimeString();
});
paras.forEach((p) => {
console.log('[p.innerHTML]: ', p.innerHTML);
});
//[p.innerHTML]: Lorem, ipsum dolor.9:42:54 AM
//[p.innerHTML]: Lorem ipsum dolor sit amet.9:42:54 AM
//[p.innerHTML]: Lorem ipsum dolor sit amet, consectetur adipisicing
</script>
說明拷貝對象中的DOM 元素髮生了變化,視圖會發生更新。
HTMLCollection
對於 HTMLCollection 也是這樣的,
<script>
const paras = document.getElementsByClassName('para');
const copy = Array.from(paras);
copy.forEach((cp) => {
cp.innerHTML += new Date().toLocaleTimeString();
});
[...paras].forEach((p) => {
console.log('[p.innerHTML]: ', p.innerHTML);
});
//[p.innerHTML]: Lorem, ipsum dolor.9:42:54 AM
//[p.innerHTML]: Lorem ipsum dolor sit amet.9:42:54 AM
//[p.innerHTML]: Lorem ipsum dolor sit amet, consectetur adipisicing elit.9:42:54 AM
</script>
需要註意的是,這裡HTMLCollection 類數組是沒有forEach 方法的, 所有我們用擴展元算符(其實也是淺拷貝)將其轉換成了一個數組。
4. 二者有什麼區別?
最重要的區別是, HTMLCollection 僅包含 tags(以及id/name分別標記的) 元素, 而 NodeList 包含所有的節點。 例如:
-
元素節點
-
屬性節點
-
文本節點(空白字元也會被視作文本節點)
-
註釋節點
示例:
<body>
<ul id="myList">
<!-- List items -->
<li name="li-name-01" id="li-id-01">List item 1</li>
<li name="li-name-02" id="li-id-02">List item 2</li>
<li name="li-name-03" id="li-id-03">List item 3</li>
<li name="li-name-04" id="li-id-04">List item 4</li>
<li name="li-name-05" id="li-id-05">List item 5</li>
</ul>
</body>
<script>
const ul = document.getElementById('myList');
console.log('[ul.children]: ', ul.children);
console.log('[ul.childNodes]: ', ul.childNodes);
</script>
這意味著,對於有id節點的 HTMLCollection 返回類型, 你可以這樣去訪問:
console.log('[li[0]]: ', li[0]); //li#li-01
console.log("[li['li-01']]: ", li['li-01']);//li#li-01
並且這二者完全一樣:
console.log(li[0] === li['li-01']);//true
name 也是如此
另外,儘管如此,HTMLCollection/NodeList 的 item 方法依舊僅能通過索引訪問,而不能夠通過id/name 訪問。
const li = document.getElementsByTagName('li');
const _li = document.querySelectorAll('li');
//以下列印: li#li-03
console.log('[li.item(2)]: ', li.item(2));
console.log('[_li.item(2)]: ', _li.item(2));
//以下列印: li#li-01
console.log('[li.item("")]: ', li.item(''));
console.log('[li.item("li-03")]: ', li.item('li-03'));
console.log('[_li.item("")]: ', _li.item(''));
console.log('[_li.item("li-03")]: ', _li.item('li-03'));
即item參數如果接收一個非數值參數,將預設返回第一個元素,如果沒有元素,那麼返回 null!