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

element.siblings가 HTMLCollection을 반환하고 HTMLCollections에 forEach () 메소드가 없기 때문에 @Daut 예
Freddo

1
이봐, 구글 검색기! 이 더블 체크를 읽는다면 foreach 대신 E가 대문자로되어 있는지 확인하십시오.
Robert Sinclair

답변:


127

첫 번째 옵션 : forEach를 간접적으로 호출

parent.children객체와 같은 배열입니다. 다음 해결책을 사용하십시오.

const parent = this.el.parentElement;

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

parent.childrenIS의 NodeList객체 때문에 같은 배열 인 유형 :

  • 그것은 포함 length노드 수를 나타내는 특성
  • 각 노드는 0부터 시작하는 숫자 이름의 특성 값입니다. {0: NodeObject, 1: NodeObject, length: 2, ...}

이 기사 에서 자세한 내용을 참조하십시오 .


두 번째 옵션 : 반복 가능한 프로토콜 사용

parent.childrenHTMLCollection: 어떤 구현하는 반복 가능한 프로토콜을 . ES2015 환경에서는 HTMLCollectioniterables를 허용하는 모든 구성과 함께 사용할 수 있습니다 .

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 ..
Jérémy

parent.children이 그것이 nodeList임을 알려주도록 사용할 브라우저. Firefox에서는 HTMLCollection이라고 알려줍니다. 그것이 nodeList라면, .forEach ()는 작동합니다
Freddo

104

parent.children배열이 아닙니다. HTMLCollection이며 forEach메서드 가 없습니다 . 먼저 배열로 변환 할 수 있습니다. 예를 들어 ES6에서 :

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

또는 스프레드 연산자 사용 :

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

9
이 솔루션은 Array 프로토 타입을 망쳐 놓는 것보다 훨씬 더 좋습니다.
Daut

그리고이 답변은 OPs 질문에 대한 정답입니다. parent.children는 .forEach 방법이 없습니다 HTMLCollection입니다
Freddo

18

parent.children기술적으로 html Collection노드 목록 목록 을 반환합니다 . 그것은 객체와 같은 배열이지만 배열은 아니므로 직접 배열 함수를 호출 할 수 없습니다. 이러한 맥락에서이를 실제 배열로 변환하는 데 사용할 수 있습니다 .Array.from()

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

아니, parent.children은 nodeList가 아니라 HTML Collection을 반환합니다. 같은 것이 아닙니다. 그것이 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

@nnnnnn 아래 답변을 참조하십시오.
Dmitri Pavlutin

배열에 객체 배열과 같은 변환하는 방법은 여러 가지가 있습니다 :)이 그것의 하나입니다
드미트리

@DmitriyLoskutov 변환 할 필요가 없습니다. JavaScript는 오리 입력 언어입니다. 이 기능을 사용하십시오.
Dmitri Pavlutin

5

그 때문에 parent.childrenA는 NodeList를 , 그리고 상기지지 않는다 .forEach(NodeList의 구조가 아니라 배열처럼 배열이기 때문에) 따라서, 첫번째 방법을 사용하여 배열로 변환하여 호출 할

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

아니요, NodeList가 아니며 HTML 모음입니다
Freddo

5

필요forEach없으며 다음 from과 같이의 두 번째 매개 변수 만 사용하여 반복 할 수 있습니다 .

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의 질문의 목표였습니다.
Armfoot

그러나 문제는 OP의 질문이 nodeList가 아닌 HTML Collection과 관련되어 있다는 것입니다. 그래서 대답은 단순히 질문에 대답하지 않았습니다
Freddo

@Cedric이 답변은 Array.from첫 번째 매개 변수에 제공된 객체를 배열로 변환하기 때문에 HTML 컬렉션을 반복 합니다. 결과는 추가 루프 ( MDN 문서) 가 필요없는 madox2의 답변 과 동일 합니다. forEachArray.from
Armfoot

4

다음 NodeList과 같이 반복하려고 하면 :

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

이런 식으로 루프하는 것이 좋습니다.

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

개인적으로, 나는 여러 가지 방법을 시도했지만 대부분을 반복하고 싶었으므로 대부분 작동하지 않았습니다. NodeList 매력적 시도해보십시오!

NodeList배열이 아니라 우리가 사용하는 배열로 취급Array. 그래서, 당신은이 오래된 브라우저에서 지원되지 않는다는 것을 알아야합니다!

에 대한 자세한 정보가 필요하십니까 NodeList? MDN에 대한 설명서를 읽으십시오 .


1
이 답변은 분명히 nodeList에서 작동합니다. 문제는 parent.children이 nodeList가 아닌 HTML Collection을 반환한다는 것입니다.
Freddo

3

ES6의 기능 ( 화살표 기능 )을 사용하므로 다음과 같이 for 루프 를 사용할 수도 있습니다 .

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


공감. ES6 구문이 얼마나 엉망입니까? 울고 싶고 C ++ 배경에서 왔습니다 ...
Freddo

1

사용자가 입력하면 확인할 수 있습니다 대해 forEach를 올바르게 입력 한 경우, foreach 문을 작동하지 않습니다 다른 프로그래밍 언어처럼.


0

당신이 사용할 수있는 childNodes대신에 children, childNodes또한 브라우저 호환성 문제, 추가 정보를 고려하고 더 신뢰할 여기를 :

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

또는 스프레드 연산자 사용 :

[...parent.children].forEach(function (child) {
    console.log(child)
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.