As I've answered questions on this website, I've began to use .forEach()
a lot more. I've also started using document.getElementsByClassName()
, or document.querySelectorAll()
a lot more.
I've recently noticed that sometimes, .forEach()
works, and sometimes it doesn't. After a bit of research, I found out that you can't .forEach()
through a NodeList
. Then I went to this answer and found out that you can .forEach()
on a NodeList.
Note: I've also added 2 snippets below in which .forEach()
works, and doesn't work. It seems to work for document.querySelectorAll()
but not document.getElementsByClassName()
, but why? Don't they both return a NodeList
?
.forEach()
on some NodeLists
, but not all?.forEach()
works on this snippet.
let text = document.querySelectorAll(".text");
console.log(typeof text);
text.forEach(e => {
console.log(e);
});
<div class="text">Text</div>
<div class="text">Text</div>
<div class="text">Text</div>
<div class="text">Text</div>
.forEach()
doesn't work on this snippet.
let text = document.getElementsByClassName("text");
console.log(typeof text);
text.forEach(e => {
console.log(e);
});
<div class="text">Text</div>
<div class="text">Text</div>
<div class="text">Text</div>
<div class="text">Text</div>
It's because querySelectorAll
returns a NodeList
, but getElementsByClassName
returns a HTMLCollection
:
let querySelector = document.querySelectorAll(".text");
let className = document.getElementsByClassName("text");
console.log(querySelector.constructor.name);
console.log(className.constructor.name);
<div class="text">Text</div>
<div class="text">Text</div>
<div class="text">Text</div>
<div class="text">Text</div>
You have to convert a HTMLCollection
to an array before you can iterate over it:
let text = Array.from(document.getElementsByClassName("text"));
text.forEach(e => {
console.log(e);
});
<div class="text">Text</div>
<div class="text">Text</div>
<div class="text">Text</div>
<div class="text">Text</div>
This happens because getElementsByClassName
doesn't returns an array but a HTMLCollection
. It's an array-like
object, as described on the documentation.
If you want to iterate over a HTMLCollection
without having to convert anything, you could use:
const list = document.getElementsByClassName('text');
const matches = Array.prototype.forEach.call(list, (el) => console.log(el));
I've added a snippet to clarify this works fine:
const list = document.getElementsByClassName('text');
const matches = Array.prototype.forEach.call(list, (el) => console.log(el));
<div class="text"></div>
<div class="text"></div>
<div class="text"></div>
<div class="text"></div>
References:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With