[javascript] HTMLCollection 요소의 For 루프

에서 모든 요소의 id를 가져 오려고합니다 HTMLCollectionOf. 다음 코드를 작성했습니다.

var list = document.getElementsByClassName("events");
console.log(list[0].id);
for (key in list) {
    console.log(key.id);
}

그러나 콘솔에서 다음과 같은 결과가 나타납니다.

event1
undefined

내가 기대 한 것이 아닙니다. 왜 두 번째 콘솔 출력 undefined이지만 첫 번째 콘솔 출력은 event1무엇입니까?



답변

원래 질문에 대한 답을 for/in잘못 사용하고 있습니다 . 귀하의 코드 key에서 색인입니다. 따라서 의사 배열에서 값을 얻으려면 수행해야 list[key]하고 ID를 가져와야 list[key].id합니다. 그러나 for/in처음부터이 작업을 수행해서는 안됩니다 .

요약 (2018 년 12 월 추가)

for/innodeList 또는 HTMLCollection을 반복하는 데 사용하지 마십시오 . 이를 피하는 이유는 다음과 같습니다.

최신 브라우저의 모든 최신 버전 (사파리, 파이어 폭스, 크롬, 에지) 모든 지원 for/ofDOM에 대한 반복은 나열 nodeList하거나 HTMLCollection.

예를 들면 다음과 같습니다.

var list = document.getElementsByClassName("events");
for (let item of list) {
    console.log(item.id);
}

오래된 브라우저 (IE와 같은 것들 포함)를 포함 시키려면 다음과 같이 작동합니다.

var list= document.getElementsByClassName("events");
for (var i = 0; i < list.length; i++) {
    console.log(list[i].id); //second console output
}

왜 사용하지 말아야하는지에 대한 설명 for/in

for/in객체의 속성을 반복하기위한 것입니다. 즉, 객체의 모든 반복 가능한 속성을 반환합니다. 배열 (배열 요소 또는 의사 배열 요소 반환)에 대해 작동하는 것처럼 보일 수 있지만 배열과 같은 요소에서 예상하지 않은 객체의 다른 속성을 반환 할 수도 있습니다. 그리고 객체 HTMLCollection또는 nodeList객체 모두 for/in반복 과 함께 반환되는 다른 속성을 가질 수 있는 것을 추측하십시오 . 방금 Chrome에서 이것을 시도하고 반복하는 방식으로 반복하면 목록의 항목 (색인 0, 1, 2 등)이 검색되지만 lengthitem속성 도 검색 됩니다. for/in반복은 단순히 HTMLCollection 작동하지 않습니다.


로 HTMLCollection을 반복 할 수없는 이유는 http://jsfiddle.net/jfriend00/FzZ2H/ 를 참조하십시오 for/in.

Firefox에서는 for/in반복시 다음 항목 (객체의 반복 가능한 모든 속성)이 반환됩니다.

0
1
2
item
namedItem
@@iterator
length

바라 건데, 지금 당신은 당신이 사용하고자하는 이유를 볼 수 있습니다 for (var i = 0; i < list.length; i++)당신은 그냥 얻을 수 있도록 대신에 0, 1그리고 2당신의 반복이다.


다음은 2015-2018 기간 동안 브라우저가 어떻게 진화했는지에 대한 진화입니다. 위에 설명 된 옵션을 사용할 수 있으므로 최신 브라우저에서는이 중 어느 것도 필요하지 않습니다.

2015 년 ES6 업데이트

ES6 Array.from()에는 배열과 같은 구조를 실제 배열로 변환하는 기능 이 추가되었습니다 . 이를 통해 다음과 같이 직접 목록을 열거 할 수 있습니다.

"use strict";

Array.from(document.getElementsByClassName("events")).forEach(function(item) {
   console.log(item.id);
});

실무 데모 (2016 년 4 월 기준 Firefox, Chrome 및 Edge) : https://jsfiddle.net/jfriend00/8ar4xn2s/


2016 년 ES6 업데이트

이제 코드에 이것을 추가하여 a NodeList및 a 와 함께 ES6 for / of 구문을 사용할 수 있습니다 HTMLCollection.

NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

그런 다음 다음을 수행 할 수 있습니다.

var list = document.getElementsByClassName("events");
for (var item of list) {
    console.log(item.id);
}

현재 버전의 Chrome, Firefox 및 Edge에서 작동합니다. 이는 Array 반복자를 NodeList 및 HTMLCollection 프로토 타입 모두에 연결하여 반복 할 때 Array 반복자를 사용하여 반복하기 때문에 작동합니다.

실무 데모 : http://jsfiddle.net/jfriend00/joy06u4e/ .


2016 년 12 월 ES6의 두 번째 업데이트

2016 년 12 월 현재 Symbol.iteratorChrome v54 및 Firefox v50이 기본적으로 지원되므로 아래 코드는 저절로 작동합니다. 아직 Edge 용으로 제공되지 않습니다.

var list = document.getElementsByClassName("events");
for (let item of list) {
    console.log(item.id);
}

실무 데모 (Chrome 및 Firefox) : http://jsfiddle.net/jfriend00/3ddpz8sp/

2017 년 12 월 ES6의 세 번째 업데이트

12 월 2017,이 기능 A의 가장자리 41.16299.15.0의 작품 nodeList에서와 같은 document.querySelectorAll(),하지만 아닌 HTMLCollection처럼 document.getElementsByClassName()당신이 그래서 수동을 위해 가장자리에서 사용하는 반복자를 할당합니다 HTMLCollection. 하나의 컬렉션 유형을 수정했지만 다른 유형은 수정하지 않는 것은 완전히 신비입니다. 그러나 현재 최신 버전의 Edge에서는 document.querySelectorAll()ES6 for/of구문으로 결과를 사용할 수 있습니다 .

이 모두를 테스트 그래서 나는 또한 jsFiddle 위가 업데이트 HTMLCollectionnodeList별도로하고 jsFiddle 자체 출력을 캡처합니다.

2018 년 3 월 ES6 용 네 번째 업데이트

mesqueeeb 당, Symbol.iterator지원이 내장 된 사파리로도 사용할 수 있도록 for (let item of list)중 하나에 대해 document.getElementsByClassName()document.querySelectorAll().

2018 년 4 월 ES6의 다섯 번째 업데이트

분명히 2018 년 가을에 HTMLCollectionwith 를 반복하는 지원 for/of이 Edge 18에 제공 될 것입니다.

2018 년 11 월 ES6 여섯 번째 업데이트

Microsoft Edge v18 (2018 년 가을 Windows 업데이트에 포함)을 사용하면 Edge에서 for / of를 사용하여 HTMLCollection과 NodeList를 모두 반복 할 수 있습니다.

따라서 모든 최신 브라우저에는 for/ofHTMLCollection 및 NodeList 객체의 반복을 기본적으로 지원 합니다.


답변

for/ inon NodeList또는 HTMLCollections를 사용할 수 없습니다 . 그러나 Array.prototype메소드를 .call()전달하고 NodeList또는 HTMLCollection로 전달 하는 한 일부 메소드 를 사용할 수 있습니다 this.

따라서 jfriend00의 for루프에 대한 대안으로 다음을 고려하십시오 .

var list= document.getElementsByClassName("events");
[].forEach.call(list, function(el) {
    console.log(el.id);
});

이 기술을 다루는 MDN에 대한 좋은 기사 가 있습니다. 브라우저 호환성에 대한 경고는 다음과 같습니다.

[…] (A와 같은 호스트 개체를 전달 NodeList로)
this(예 : 기본 방법은 forEach) 모든 브라우저에서 작동이 보장되지는 않으며 일부에서 실패하는 것으로 알려져있다.

따라서이 방법은 편리하지만 for루프는 브라우저와 가장 호환되는 솔루션 일 수 있습니다.

업데이트 (2014 년 8 월 30 일) : 결국 ES6 for/of !

var list = document.getElementsByClassName("events");
for (const el of list)
  console.log(el.id);

최신 버전의 Chrome 및 Firefox에서 이미 지원됩니다.


답변

ES6에서, 당신이 뭔가를 같이 할 수있는 [...collection], 또는 Array.from(collection),

let someCollection = document.querySelectorAll(someSelector)
[...someCollection].forEach(someFn)
//or
Array.from(collection).forEach(someFn)

예 :-

    navDoms = document.getElementsByClassName('nav-container');
    Array.from(navDoms).forEach(function(navDom){
     //implement function operations
    });


답변

이 두 줄을 추가 할 수 있습니다.

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

HTMLCollectiongetElementsByClassNamegetElementsByTagName에 의해 리턴됩니다.

querySelectorAll에 의해 NodeList 가 리턴됩니다.

이와 같이 당신은 forEach를 할 수 있습니다 :

var selections = document.getElementsByClassName('myClass');

/* alternative :
var selections = document.querySelectorAll('.myClass');
*/

selections.forEach(function(element, i){
//do your stuffs
});


답변

IE 11Firefox 49 에서 forEach를 사용하는 데 문제가 있습니다.

이 같은 해결 방법을 찾았습니다

Array.prototype.slice.call(document.getElementsByClassName("events")).forEach(function (key) {
        console.log(key.id);
    }


답변

대안 Array.from은 사용하는 것입니다Array.prototype.forEach.call

각각:
Array.prototype.forEach.call(htmlCollection, i => { console.log(i) });

지도: Array.prototype.map.call(htmlCollection, i => { console.log(i) });

요법 …


답변

forIE9 이상인 경우 es6 기능을 사용하여 루핑 을 피할 이유가 없습니다 .

ES5에는 두 가지 좋은 옵션이 있습니다. 첫째, 당신은 “대출”은 수 ArrayforEach에반 언급 .

그러나 더 나은 …

를 사용 Object.keys()하면 자동으로 “속성을 소유”하는 필터 있습니다 forEach.

즉, Object.keys본질적으로 a를 for... in사용하는 것과 동일 HasOwnProperty하지만 훨씬 더 부드럽습니다.

var eventNodes = document.getElementsByClassName("events");
Object.keys(eventNodes).forEach(function (key) {
    console.log(eventNodes[key].id);
});