Why is forEach not working for children?

China☆狼群 提交于 2019-12-17 23:26:37

问题


I have a <div> with some child <div> in it. E.g.

<div id="niceParent">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

I tried to loop through them with the forEach function, because I thought that document.getElementById("niceParent").children is an array, as I can access the elements with

console.log(document.getElementById("niceParent").children[1]);
console.log(document.getElementById("niceParent").children[2]);
console.log(document.getElementById("niceParent").children[3]);
console.log(document.getElementById("niceParent").children[4]);

Hence I tried

document.getElementById("niceParent").children.forEach(function(entry) {
  console.log(entry);
});

which is not working. I get

TypeError: document.getElementById(...).children.forEach is not a function

As a workaround I also tried it with a—much more complicated—for..in loop:

for (var i in document.getElementById("niceParent").children) {
  if (document.getElementById("niceParent").children[i].nodeType == 1) console.log(document.getElementById("niceParent").children[i]);
}

which worked as expected.

Why?


回答1:


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);



回答2:


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(…);



回答3:


A cleaner and more modern way to convert a HTMLCollection like .children to an array to use forEach() (or map(), etc.) is to use the spread synthax ... 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.




回答4:


You can also do this:

NodeList.prototype.forEach = HTMLCollection.prototype.forEach = Array.prototype.forEach;

And after this you can call forEach on your collection:

document.getElementById("niceParent").children.forEach(...)

The best and most secure way would be actually to only add forEach in cases when it doesn't already exist:

if (window.NodeList && !NodeList.prototype.forEach) {
   NodeList.prototype.forEach = Array.prototype.forEach;
}
if (window.HTMLCollection && !HTMLCollection.prototype.forEach) {
   HTMLCollection.prototype.forEach = Array.prototype.forEach;
}


来源:https://stackoverflow.com/questions/15094886/why-is-foreach-not-working-for-children

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!