childNode를 통해 루프


85

다음과 같이 childNodes를 반복하려고합니다.

var children = element.childNodes;
children.forEach(function(item){
    console.log(item);
});

그러나, 출력 Uncaught TypeError: undefined is not a function에 의한 forEach기능. 나는 또한 children대신 사용하려고 childNodes하지만 아무것도 변경되지 않았습니다.

무슨 일인지 아는 사람 있나요?

답변:


124

변수 childrenNodeList인스턴스이고 NodeLists는 참이 아니므로 메서드를 Array상속하지 않습니다 forEach.

또한 일부 브라우저는 실제로 지원합니다. nodeList.forEach


ES5

slicefrom Array을 사용 NodeList하여을 적절한 Array.

var array = Array.prototype.slice.call(children);

단순히을 사용 하여 as 컨텍스트 call를 호출 forEach하고 전달할 수도 NodeList있습니다.

[].forEach.call(children, function(child) {});


ES6

당신이 사용할 수있는 from당신을 변환하는 방법을 NodeListArray.

var array = Array.from(children);

또는 다음 과 같이 스프레드 구문을... 사용할 수도 있습니다.

let array = [ ...children ];


사용할 수있는 해킹입니다 NodeList.prototype.forEach = Array.prototype.forEach그리고 당신은 사용할 수있는 forEach모든으로 NodeList그들에게 때마다 변환 할 필요없이.

NodeList.prototype.forEach = Array.prototype.forEach
var children = element.childNodes;
children.forEach(function(item){
    console.log(item);
});

좋은 설명과이를 수행하는 다른 방법은 NodeLists, Arrays, NodeLists 변환 및 DOM 이해에 대한 포괄적 인 내용을 참조하십시오 .


NodeList를 순수한 배열로 어떻게 변환 할 수 있습니까?
user3828771

예제로 업데이트되었지만 게시 한 링크를 읽으십시오.
GillesC

2
또는 다음을 수행 할 수 있습니다.[].forEach.call(element.childNodes, child => console.log(child))
XåpplI'-I0llwlg'I-

2
더 멋진 es6 방식 : let items = [ ...children ]어레이로 변환
zackify

2
NodeList에 Array 메서드를 적용하는 데 큰 문제가 있습니다. node.childNodes와 같은 NodeList는 라이브 목록이며 루프 중에 DOM을 조작하면 NodeList가 변경 될 수 있습니다. 즉, forEach ()에 대한 콜백이 호출되지 않습니다. 목록의 모든 요소 또는 원래 목록에 있던 것보다 많은 요소가 예상치 못한 결과를 초래합니다. 루프하기 전에 NodeList를 배열로 바꾸는 것이 좋습니다.
stephband

30

나는 파티에 매우 늦었지만 이후 element.lastChild.nextSibling === null다음은 나에게 가장 간단한 옵션처럼 보입니다.

for(var child=element.firstChild; child!==null; child=child.nextSibling) {
    console.log(child);
}

1
가장 간단한 옵션은 일반 "for"루프를 사용하는 것입니다. 그러나 당신의 선택은 흥미 롭습니다.
Kirill Reznikov

이 최선을 같은 나는 ... 같은 논리가 아니라 필요로 변환을 구현하기 위해 계획되었다
Ujjwal 싱

23

다음은 for-in루프를 사용 하여 수행하는 방법 입니다.

var children = element.childNodes;

for(child in children){
    console.log(children[child]);
}

14
체크를 잊어 버렸습니다 : if (children.hasOwnProperty (child)) {// code here} 아니면 "length"등과 같은 원치 않는 props를 반복합니다!
Kirill Reznikov

8
더 좋은 for ... of ...점은를 사용 하십시오.하지만 ES6 구문입니다.
Jespertheend

5

을 사용하여 다른 방법을 추가하는 것을 거부 할 수 없습니다 childElementCount. 주어진 부모에서 자식 요소 노드의 수를 반환하므로 반복 할 수 있습니다.

for(var i=0, len = parent.childElementCount ; i < len; ++i){
    ... do something with parent.children[i]
    }

4

for루프로 시도하십시오 . forEach노드 모음이기 때문에 오류가 발생 nodelist합니다.

또는 노드 목록을 배열로 변환해야합니다.

function toArray(obj) {
  var array = [];
  for (var i = 0; i < obj.length; i++) { 
    array[i] = obj[i];
  }
return array;
}

또는 이것을 사용할 수 있습니다

var array = Array.prototype.slice.call(obj);

3
const results = Array.from(myNodeList.values()).map(parser_item);

NodeList는 Array가 아니지만 NodeList.values ​​()는 Array Iterator를 반환하므로 Array로 변환 할 수 있습니다.


2

[역 순회]를 시도해보십시오.

var childs = document.getElementById('parent').childNodes;
var len = childs.length;
if(len --) do {
    console.log('node: ', childs[len]);
} while(len --);

OR [순회 순회]

var childs = document.getElementById('parent').childNodes;
var len = childs.length, i = -1;
if(++i < len) do {
    console.log('node: ', childs[i]);
} while(++i < len);

간단한 for 루프는 while 루프보다 더 읽기 쉽습니다. 작성자는 역순 / 역순 순회를 요청하지 않습니다.
Kirill Reznikov

2

다음은 NodeList. 이 방법은 사용 Array'들 forEach과 같이 :

Array.prototype.forEach.call(element.childNodes, f)

f첫 번째 매개 변수로 자식 노드를 받고 두 번째 매개 변수로 인덱스를받는 반복기 함수는 어디에 있습니까 ?

NodeList를 두 번 이상 반복해야하는 경우 다음과 같이 작은 기능 유틸리티 메서드를 만들 수 있습니다.

const forEach = f => x => Array.prototype.forEach.call(x, f);

// For example, to log all child nodes
forEach((item) => { console.log(item); })(element.childNodes)

// The functional forEach is handy as you can easily created curried functions
const logChildren = forEach((childNode) => { console.log(childNode); })
logChildren(elementA.childNodes)
logChildren(elementB.childNodes)

( map()및 기타 Array 함수에 대해 동일한 트릭을 수행 할 수 있습니다 .)


0

이런 종류의 일을 많이한다면 직접 함수를 정의하는 것이 좋습니다.

if (typeof NodeList.prototype.forEach == "undefined"){
    NodeList.prototype.forEach = function (cb){
        for (var i=0; i < this.length; i++) {
            var node = this[i];
            cb( node, i );
        }
    };
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.