Loop through childNodes
JavascriptLoopsChildrenJavascript Problem Overview
I'm trying to loop through childNodes like this:
var children = element.childNodes;
children.forEach(function(item){
console.log(item);
});
However, it output Uncaught TypeError: undefined is not a function
due to forEach
function. I also try to use children
instead of childNodes
but nothing changed.
Does anybody know what's going on?
Javascript Solutions
Solution 1 - Javascript
The variable children
is a NodeList
instance and NodeList
s are not true Array
and therefore they do not inherit the forEach
method.
Also some browsers actually support it nodeList.forEach
ES5
You can use slice
from Array
to convert the NodeList
into a proper Array
.
var array = Array.prototype.slice.call(children);
You could also simply use call
to invoke forEach
and pass it the NodeList
as context.
[].forEach.call(children, function(child) {});
ES6
You can use the from
method to convert your NodeList
into an Array
.
var array = Array.from(children);
Or you can also use the spread syntax ...
like so
let array = [ ...children ];
A hack that can be used is NodeList.prototype.forEach = Array.prototype.forEach
and you can then use forEach
with any NodeList
without having to convert them each time.
NodeList.prototype.forEach = Array.prototype.forEach
var children = element.childNodes;
children.forEach(function(item){
console.log(item);
});
See A comprehensive dive into NodeLists, Arrays, converting NodeLists and understanding the DOM for a good explanation and other ways to do it.
Solution 2 - Javascript
I'm very late to the party, but since element.lastChild.nextSibling === null
, the following seems like the most straightforward option to me:
for(var child=element.firstChild; child!==null; child=child.nextSibling) {
console.log(child);
}
Solution 3 - Javascript
Here is how you can do it with for-in
loop.
var children = element.childNodes;
for(child in children){
console.log(children[child]);
}
Solution 4 - Javascript
const results = Array.from(myNodeList.values()).map(parser_item);
NodeList is not Array but NodeList.values() return a Array Iterator, so can convert it to Array.
Solution 5 - Javascript
Couldn't resist to add another method, using childElementCount
. It returns the number of child element nodes from a given parent, so you can loop over it.
for(var i=0, len = parent.childElementCount ; i < len; ++i){
... do something with parent.children[i]
}
Solution 6 - Javascript
Try with for
loop. It gives error in forEach
because it is a collection of nodes nodelist
.
Or this should convert node-list to array
function toArray(obj) {
var array = [];
for (var i = 0; i < obj.length; i++) {
array[i] = obj[i];
}
return array;
}
Or you can use this
var array = Array.prototype.slice.call(obj);
Solution 7 - Javascript
Try this [reverse order traversal]:
var childs = document.getElementById('parent').childNodes;
var len = childs.length;
if(len --) do {
console.log('node: ', childs[len]);
} while(len --);
OR [in order traversal]
var childs = document.getElementById('parent').childNodes;
var len = childs.length, i = -1;
if(++i < len) do {
console.log('node: ', childs[i]);
} while(++i < len);
Solution 8 - Javascript
Here is a functional ES6 way of iterating over a NodeList
. This method uses the Array
's forEach
like so:
Array.prototype.forEach.call(element.childNodes, f)
Where f
is the iterator function that receives a child nodes as it's first parameter and the index as the second.
If you need to iterate over NodeLists more than once you could create a small functional utility method out of this:
const forEach = f => x => Array.prototype.forEach.call(x, f);
// For example, to log all child nodes
forEach((item) => { console.log(item); })(element.childNodes)
// The functional forEach is handy as you can easily created curried functions
const logChildren = forEach((childNode) => { console.log(childNode); })
logChildren(elementA.childNodes)
logChildren(elementB.childNodes)
(You can do the same trick for map()
and other Array functions.)
Solution 9 - Javascript
If you do a lot of this sort of thing then it might be worth defining the function for yourself.
if (typeof NodeList.prototype.forEach == "undefined"){
NodeList.prototype.forEach = function (cb){
for (var i=0; i < this.length; i++) {
var node = this[i];
cb( node, i );
}
};
}