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

변수 children는 NodeList인스턴스이고 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당신을 변환하는 방법을 NodeList로 Array.

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.