Why is forEach not working for children?

Because .children contains an HTMLCollection [MDN], not an array. An HTMLCollection object is an array-like object, which exposes a .length property and has numeric properties, just like arrays, but it does not inherit from Array.prototype and thus is not an array.

You can convert it to an array using Array.prototype.slice:

var children = [].slice.call(document.getElementById(...).children);

ECMAScript 6 introduces a new API for converting iterators and array-like objects to real arrays: Array.from [MDN]. Use that if possible since it makes the intent much clearer.

var children = Array.from(document.getElementById(...).children);

A way to convert a HTMLCollection like .children to an array to use forEach() (or map(), etc.) is to use the spread syntax ... in an array [].

var children = [...document.getElementById('x').children];

for example:

[...document.getElementById('x').children].forEach(child => console.log(child))

This is an es6 feature. It will work on all modern browser.

[...document.getElementById('niceParent').children].forEach(child => console.log(child.textContent))
<div id="niceParent">
  <div>a</div>
  <div>b</div>
  <div>c</div>
  <div>d</div>
</div>

If, on visual studio code, you faced the error:

Type 'IterableIterator' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators.

Instead of

[...document.getElementById('niceParent').children]

you can rely on

Array.from(document.getElementById('niceParent').children)

More on downlevelIteration


Element.children is not an array. It is an object called an HTMLCollection. These do not have an array’s methods (though they do have the length property).

To loop through it, you'll have to convert it into an array, which you can do using Array.prototype.slice:

var children = Array.prototype.slice.call(document.getElementById("niceParent").children);

children.forEach(…);