Cảm ơn bạn!
So sánh HTMLCollection vs NodeList trong JavaScript
Khi sử dụng method querySelectorAll()
, chúng ta nhận được một NodeList. Ngược lại, với getElementsByTagName()
chúng ta sẽ lấy được HTMLCollection. Trong bài viết này, chúng ta sẽ cùng so sánh NodeList vs HTMLCollection trong JavaScript nhé 😁.
NodeList vs HTMLCollection
Để so sánh NodeList vs HTMLCollection, mình xin đưa ra một ví dụ sau:
<div id="content">
<a href="https://homiedev.com/hoc-javascript-co-ban/">Học JavaScript cơ bản</a>
<a href="https://homiedev.com/javascript-projects-for-beginners/">100+ JavaScript Projects</a>
</div>
Tiếp theo sử dụng JavaScript, chúng ta có thể lấy tất cả thẻ a của div#content
bằng cách:
// lấy tất cả thẻ a sử dụng querySelectorAll hoặc getElementsByTagName
const elements1 = document.querySelectorAll("a");
const elements2 = document.getElementsByTagName("a");
console.log(
"querySelectorAll",
elements1,
"getElementsByTagName",
elements2
);
Kết quả chúng ta được:
Chúng ta có thể sử dụng getElementsByClassName()
hoặc getElementsByTagName()
, kết quả sẽ trả về một HTMLCollection. Sử dụng querySelectorAll()
hoặc getElementsByName()
nếu muốn kết quả là một NodeList.
Đầu tiên, chúng ta có thể nói về điểm giống nhau giữa NodeList và HTMLCollection đó chính là cả hai đều là array-like object, chúng nhìn rất giống mảng nhưng thực chất không phải là mảng.
Array-like là một object, đặc biệt ở chỗ nó có thuộc tính length
và những thuộc tính với key là số nguyên, vì lý do đó chúng nhìn rất giống với mảng trong JavaScript.
Để hiểu rõ hơn về array-like object trong JavaScript, bạn có thể đọc bài viết: Array-like Object trong JavaScript là gì? Tại sao bạn cần nên biết.
Vì lý do lầm tưởng là mảng, nên nhiều bạn sử dụng method của mảng để lặp qua, ví dụ:
const elements = document.getElementsByTagName("a"); // HTMLCollection
elements.forEach(element => {
console.log(element);
});
// lỗi: elements.forEach is not a function
Lỗi sẽ xảy ra vì kết quả nhận được từ getElementsByTagName()
là một HTMLCollection và nó là một array-like object. Chúng ta có thể lặp bằng cách chuyển nó sang mảng sử dụng Array.from()
hoặc spread operator:
const elements = document.getElementsByTagName("a"); // HTMLCollection
const array = Array.from(elements);
array.forEach((element) => {
console.log(element);
});
// OK
Với NodeList, nếu các bạn nhìn vào hình trên sẽ thấy nó có method là forEach()
, nên chúng ta có thể lặp qua các phần tử nếu muốn:
const elements = document.querySelectorAll("a"); // NodeList
elements.forEach(element => {
console.log(element);
});
// OK
Ở trên là điểm khác biệt đầu tiên giữa NodeList và HTMLCollection chúng ta có thể nhận thấy.
Điểm khác biệt tiếp theo có thể kể đến là sử dụng NodeList để lấy phần tử theo ý muốn thì chúng ta sẽ sử dụng index:
const elements = document.querySelectorAll("a"); // NodeList
// cách truy xuất nhìn rất giống mảng
// tuy nhiên elements là một array-like
console.log(elements[0]);
Với HTMLCollection, nhìn vào hình trên, chúng ta có thể thấy nó có một method tên là namedItem()
, method này sử dụng name
hoặc id
để lấy phần tử theo ý muốn và trả null nếu không tìm thấy.
Như vậy ta có thể sử dụng name
, id
hoặc index để lấy phần tử theo ý muốn khi sử dụng HTMLCollection.
<div id="content">
Homiedev.com
<a name="link_1" id="link_id1" href="https://homiedev.com/hoc-javascript-co-ban/">Học JavaScript cơ bản</a>
<a href="https://homiedev.com/javascript-projects-for-beginners/">100+ JavaScript Projects</a>
</div>
const elements = document.getElementsByTagName("a"); // HTMLCollection
console.log(elements[0]); // sử dụng index
console.log(elements.namedItem("link_id1")); // get bằng id
console.log(elements.namedItem("link_1")); // get bằng name
Điểm khác biệt tiếp theo đó là khi thao tác DOM, những thay đổi có liên quan được update cho HTMLCollection (live), với NodeList (sử dụng querySelectorAll()) những thay đổi này sẽ không được update (static).
const elements1 = document.querySelectorAll("a"); // static
const elements2 = document.getElementsByTagName("a"); // live
const content = document.getElementById("content");
// thêm một phần tử vào `div#content`
content.appendChild(document.createElement("a"));
console.log(elements1.length); // 2
console.log(elements2.length); // 3
NodeList có 2 loại Live NodeList và Static NodeList. Sử dụng
querySelectorAll()
ta sẽ nhận được Static NodeList. Trường hợp là Live NodeList ví dụNode.childNodes
.const parent = document.getElementById('homiedev'); let childNodes = parent.childNodes; // NodeList console.log(childNodes.length); // 2 parent.appendChild(document.createElement('div')); console.log(childNodes.length); // 3
Hi vọng bài viết giúp ích cho các bạn. Đừng quên theo dõi blog và đăng ký kênh youtube homiedev để theo dõi những nội dung về Frontend nhé ^^. Chúc các bạn học tốt.