web-dev-qa-db-ja.com

forEachが子供のために働いていないのはなぜですか?

私は_<div>_に子__<div>_を入れています。例えば。

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

document.getElementById("niceParent").childrenは配列であると思ったので、forEach関数でそれらをループしてみました。

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

したがって、私は試しました

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

機能していません。私は得る

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

回避策として、さらに複雑な_for..in_ループでも試してみました。

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

期待どおりに動作しました。

どうして?

31
erik

.childrenには NodeListが含まれているため[MDN] 、配列ではありません。 NodeListオブジェクトは、array-likeオブジェクトであり、.lengthプロパティを公開し、のように数値プロパティを持ちます配列ですが、Array.prototypeを継承しないため、配列ではありません。

Array.prototype.sliceを使用して配列に変換できます:

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

ECMAScript 6は、反復子と配列のようなオブジェクトを実際の配列に変換するための新しいAPIを導入します: Array.from[MDN] 。意図がより明確になるため、可能であればそれを使用してください。

var children = Array.from(document.getElementById(...).children);
49
Felix Kling

Element.childrennot配列です。これはHTMLCollectionと呼ばれるオブジェクトです。これらには配列のメソッドがありません(ただし、lengthプロパティはあります)。

ループするには、配列に変換する必要があります。これは Array.prototype.slice

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

children.forEach(…);
10
lonesomeday

_.children_のようなHTMLCollectionforEach()(またはmap()など)を使用する配列に変換するよりクリーンでよりモダンな方法は、 spread synthax _..._ in a array _[]_。

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

例えば:

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

これはes6の機能です。最新のすべてのブラウザで動作します。

3
aloisdg

これを行うこともできます:

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

この後、コレクションでforEachを呼び出すことができます。

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

最善かつ最も安全な方法は、実際にはforEachがまだ存在しない場合にのみ追加することです。

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