forEach is not a function error with JavaScript array

JavascriptEcmascript 6vue.js

Javascript Problem Overview


I'm trying to make a simple loop:

const parent = this.el.parentElement
console.log(parent.children)
parent.children.forEach(child => {
  console.log(child)
})

But I get the following error:

> VM384:53 Uncaught TypeError: parent.children.forEach is not a function

Even though parent.children logs:

enter image description here

What could be the problem?

Note: Here's a JSFiddle.

Javascript Solutions


Solution 1 - Javascript

First option: invoke forEach indirectly

The parent.children is an Array like object. Use the following solution:

const parent = this.el.parentElement;

Array.prototype.forEach.call(parent.children, child => {
  console.log(child)
});

The parent.children is NodeList type, which is an Array like object because:

  • It contains the length property, which indicates the number of nodes
  • Each node is a property value with numeric name, starting from 0: {0: NodeObject, 1: NodeObject, length: 2, ...}

See more details in this article.


Second option: use the iterable protocol

parent.children is an HTMLCollection: which implements the iterable protocol. In an ES2015 environment, you can use the HTMLCollection with any construction that accepts iterables.

Use HTMLCollection with the spread operatator:

const parent = this.el.parentElement;

[...parent.children].forEach(child => {
  console.log(child);
});

Or with the for..of cycle (which is my preferred option):

const parent = this.el.parentElement;

for (const child of parent.children) {
  console.log(child);
}

Solution 2 - Javascript

parent.children is not an array. It is HTMLCollection and it does not have forEach method. You can convert it to the array first. For example in ES6:

Array.from(parent.children).forEach(child => {
    console.log(child)
});

or using spread operator:

[...parent.children].forEach(function (child) {
    console.log(child)
});

Solution 3 - Javascript

A more naive version, at least you're sure that it'll work on all devices, without conversion and ES6 :

const children = parent.children;
for (var i = 0; i < children.length; i++){
    console.log(children[i]);
}

https://jsfiddle.net/swb12kqn/5/

Solution 4 - Javascript

parent.children will return a node list list, technically a html Collection. That is an array like object, but not an array, so you cannot call array functions over it directly. At this context you can use Array.from() to convert that into a real array,

Array.from(parent.children).forEach(child => {
  console.log(child)
})

Solution 5 - Javascript

parent.children is a HTMLCollection which is array-like object. First, you have to convert it to a real Array to use Array.prototype methods.

const parent = this.el.parentElement
console.log(parent.children)
[].slice.call(parent.children).forEach(child => {
  console.log(child)
})

Solution 6 - Javascript

You can check if you typed forEach correctly, if you typed foreach like in other programming languages it won't work.

Solution 7 - Javascript

There is no need for the forEach, you can iterate using only the from's second parameter, like so:

let nodeList = [{0: [{'a':1,'b':2},{'c':3}]},{1:[]}]
Array.from(nodeList, child => {
  console.log(child)
});

Solution 8 - Javascript

If you are trying to loop over a NodeList like this:

const allParagraphs = document.querySelectorAll("p");

I highly recommend loop it this way:

Array.prototype.forEach.call(allParagraphs , function(el) {
    // Write your code here
})

Personally, I've tried several ways but most of them didn't work as I wanted to loop over a NodeList, but this one works like a charm, give it a try!

The NodeList isn't an Array, but we treat it as an Array, using Array. So, you need to know that it is not supported in older browsers!

Need more information about NodeList? Please read its documentation on MDN.

Solution 9 - Javascript

That's because parent.children is a NodeList, and it doesn't support the .forEach method (as NodeList is an array like structure but not an array), so try to call it by first converting it to array using

var children = [].slice.call(parent.children);
children.forEach(yourFunc);

Solution 10 - Javascript

Since you are using features of ES6 (arrow functions), you may also simply use a for loop like this:

for(let child of [{0: [{'a':1,'b':2},{'c':3}]},{1:[]}]) { console.log(child) }

Solution 11 - Javascript

use JSON.parse()

str_json = JSON.parse(array);
str_json.forEach(function (item, index) {
    console.log(item);
});

Solution 12 - Javascript

You can use childNodes instead of children, childNodes is also more reliable considering browser compatibility issues, more info here:

parent.childNodes.forEach(function (child) {
    console.log(child)
});

or using spread operator:

[...parent.children].forEach(function (child) {
    console.log(child)
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionalexchencoView Question on Stackoverflow
Solution 1 - JavascriptDmitri PavlutinView Answer on Stackoverflow
Solution 2 - Javascriptmadox2View Answer on Stackoverflow
Solution 3 - JavascriptJeanView Answer on Stackoverflow
Solution 4 - JavascriptRajaprabhu AravindasamyView Answer on Stackoverflow
Solution 5 - JavascriptDmitriyView Answer on Stackoverflow
Solution 6 - JavascriptAbdelsalam MegahedView Answer on Stackoverflow
Solution 7 - JavascriptArmfootView Answer on Stackoverflow
Solution 8 - JavascriptElharonyView Answer on Stackoverflow
Solution 9 - JavascriptAmmar HasanView Answer on Stackoverflow
Solution 10 - JavascriptArmfootView Answer on Stackoverflow
Solution 11 - JavascriptAchmad TaufiqView Answer on Stackoverflow
Solution 12 - JavascriptSyedView Answer on Stackoverflow