forEachはJavaScript配列の関数エラーではありません


145

私は単純なループを作ろうとしています:

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

しかし、私は次のエラーを受け取ります:

VM384:53 Uncaught TypeError:parent.children.forEachは関数ではありません

たとえparent.childrenログ:

ここに画像の説明を入力してください

何が問題でしょうか?

注:これがJSFiddleです。


element.siblingsでも同じ問題が発生する
Daut

@Dautはい、element.siblingsはHTMLCollectionを返し、HTMLCollectionsにはforEach()メソッドがありません
Freddo

1
やあ、グーグルサーチャー!あなたがこのダブルリードを読んでいるなら、それがforeachではなく大文字のEを持つforEachであることを確認してください...
Robert Sinclair

回答:


127

最初のオプション:forEachを間接的に呼び出す

parent.childrenオブジェクトのような配列です。次のソリューションを使用します。

const parent = this.el.parentElement;

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

parent.childrenであるNodeListため、オブジェクトのような配列であるタイプ:

  • lengthノードの数を示すプロパティが含まれています
  • 各ノードは、0から始まる数値名のプロパティ値です。 {0: NodeObject, 1: NodeObject, length: 2, ...}

この記事の詳細をご覧ください。


2番目のオプション:反復可能なプロトコルを使用する

parent.childrenですHTMLCollection:実装する反復可能なプロトコルを。ES2015環境では、HTMLCollection反復可能オブジェクトを受け入れる任意の構造でを使用できます。

HTMLCollectionスプレッドオペレーターで使用:

const parent = this.el.parentElement;

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

または、for..ofサイクル(これは私の優先オプションです):

const parent = this.el.parentElement;

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

私があなたの解決策を使うとき、私はもう問題はありませんが、匿名化された関数内のコードは実行されません。.so ..
ジェレミー

parent.childrenがnodeListであることを通知するために使用するブラウザー。Firefoxでは、HTMLCollectionであることがわかります。nodeListの場合、.forEach()は機能します
Freddo

104

parent.childrenは配列ではありません。HTMLCollectionであり、forEachメソッドはありません。最初に配列に変換できます。たとえばES6の場合:

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

または、spread演算子を使用します。

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

9
私は、配列のプロトタイプをいじるよりも、このソリューションを好みます。
Daut

そして、この答えはOPの質問に対する正しい答え(の1つ)です。parent.childrenは.forEachメソッドを持たないHTMLCollectionです
Freddo

18

parent.childrenノードリストリスト、厳密にはhtmlコレクションを返します。これはオブジェクトのような配列ですが、配列ではないため、配列関数を直接呼び出すことはできません。このコンテキストではArray.from()、これを実際の配列に変換するために使用できます。

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

いいえ、parent.childrenはnodeListではなくHTMLコレクションを返します。同じではありません。nodeListの場合、.forEachが機能します
Freddo

12

より素朴なバージョン、少なくとも変換とES6なしで、すべてのデバイスで動作することが確実です。

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

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


2
これらの新しいES6関数はすべて、利用可能であった古き良きものとまったく同じですが、いつものように面倒な方法でJS
Freddo

8

parent.childrenHTMLCollection配列のようなオブジェクトです。まず、メソッドArrayを使用するには、それを実数に変換する必要がありArray.prototypeます。

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

2
または変換せずに、.forEach()で.call()を使用しますか?
nnnnnn 2016年

@nnnnnn以下の私の回答を参照してください。
Dmitri Pavlutin 2016年

配列のようなオブジェクトを配列に変換する方法はたくさんあります:)これはその1つです
Dmitriy

@DmitriyLoskutovあなたはそれを変換する必要はありません-JavaScriptはダックタイピング言語です。この機能を使用してください。
Dmitri Pavlutin 2016年

5

これparent.childrenは、がNodeListであり、.forEachメソッドをサポートしていないためです(NodeListは構造のような配列ですが配列ではないため)。

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

いいえ、これはNodeListではなく、HTMLコレクションです
Freddo

5

の必要forEachはありません。from次のように、の2番目のパラメータのみを使用して反復できます。

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


悲しいことに、parent.childrenはnodeListではありません... .from()は機能しません。
Freddo

@Cedricは、オブジェクトがNodeListでない場合、特にそれを処理するために新しい質問をする必要があります。ここでは、答えが本質的に間違っているか有害である場合にダウン投票が使用され、コードスニペットからわかるように、オブジェクトのすべての要素が反復されて出力されます。これがOPの質問の目的でした。
アームフット

はい、問題はOPの質問がnodeListではなくHTMLコレクションに関連していることです...だから答えは単に質問に答えていなかった
Freddo

@Cedricこの回答はArray.from、最初のパラメータで指定されたオブジェクトを配列に変換するため、HTMLコレクションに対しても繰り返されます。結果は、余分なループを必要とせずにmadox2の回答と同じですforEachArray.fromMDNドキュメント)。
アームフット

4

次のNodeListようにループしようとしている場合:

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

このようにループすることを強くお勧めします。

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

個人的に、私はいくつかの方法を試しましたが、ループしたいのでそれらのほとんどは機能しませんでした NodeListが、これは魅力のように機能します、試してみてください!

これNodeListは配列ではありませんが、配列として扱います。Array.ます。そのため、古いブラウザーではサポートされていないことを知っておく必要があります。

詳細についてはNodeListMDNに関するドキュメントをお読みください。


1
この回答は明らかにnodeListで機能します。問題は、parent.childrenがnodeListではないHTMLコレクションを返すことです...
Freddo



0

childNodes代わりに使用できます。またchildrenchildNodesブラウザの互換性の問題を考慮するとより信頼性が高くなります。詳細はこちら

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

または、spread演算子を使用します。

[...parent.children].forEach(function (child) {
    console.log(child)
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.