getElementsByClassName의 배열에서 forEach를 사용하면 "TypeError : undefined is not a function"이 발생합니다.


91

내 JSFiddle 에서는 단순히 요소 배열을 반복하려고합니다. 로그 문이 증명 하듯이 배열은 비어 있지 않습니다. 그러나 호출 forEach은 나에게 (그다지 도움 이되지 않음 )“Uncaught TypeError: undefinedis not a function”오류를 제공합니다.

나는 어리석은 짓을하고있는 것 같다. 내가 뭘 잘못하고 있죠?

내 코드 :

var arr = document.getElementsByClassName('myClass');
console.log(arr);
console.log(arr[0]);
arr.forEach(function(v, i, a) {
  console.log(v);
});
.myClass {
  background-color: #FF0000;
}
<div class="myClass">Hello</div>


8
arr은 배열이 아니라 HTMLCollection. 배열과 동일한 방법이 없습니다. developer.mozilla.org/en-US/docs/Web/API/... . 여기에 그것에 대한 SO 게시물이 있습니다 : stackoverflow.com/questions/13433799/…
Ian

같은 [1,2,3].forEach(function(v,i,a) { console.log(v); });것은 괜찮습니다. 이 예제와 배열의 차이점은 무엇입니까?
Jer

귀하 의 예제 에는 배열 이 없습니다 . 배열이라고 생각하는 이유는 무엇입니까?
Ian

3
@Jer :로가 arr instanceof Array발생할 것이다 false의 모든 프로토 방법 소용없는 그 Array와 같은 객체 () Array.prototype.forEach . arrA는 HTMLCollection 와 같은 객체 배열 (단 또는 인스턴스화 상속되지 않음 Array). 따라서 표준 for루프는 단순히 객체의 인덱스를 반복하고의 프로토 타입이 아니므로 작동합니다 Array.
Nope

1
@ Jer— 기본 제공 개체와 호스트 개체 간의 차이점을 살펴 봐야합니다. 전자는 ECMA-262를 따르고 나중에 호스트가 원하는만큼만 준수합니다. DOM에는 주로 NodeList 인터페이스를 기반으로하는 인덱스 (document.images, document.forms, form.elements, select.options 등)별로 멤버에 액세스 할 수있는 많은 객체가 있습니다 .
RobG

답변:


162

이는 배열이 아닌 HTMLCollection을document.getElementsByClassName 반환 하기 때문 입니다.

다행히도 이것은 "배열과 같은"객체 ( 객체 인 것처럼 기록되는 이유와 표준 for루프로 반복 할 수있는 이유를 설명 )이므로 다음과 같이 할 수 있습니다.

[].forEach.call(document.getElementsByClassName('myClass'), function(v,i,a) {

ES6 (최신 브라우저 또는 Babel)을 사용하면 Array.from배열과 유사한 객체에서 배열을 빌드 하는 것을 사용할 수도 있습니다 .

Array.from(document.getElementsByClassName('myClass')).forEach(v=>{

또는 배열과 유사한 객체를 배열로 확산 :

[...document.getElementsByClassName('myClass'))].forEach(v=>{

2
@Jer arguments는 하나입니다. jQuery 객체는 또 다른 것입니다. 직접 만들 수 있습니다.var a = {"0": "str1", "1": "str2", length: 2}
Ian

1
여기서는 다시 오래된 브라우저를 사용합니다. 호스트 개체를 네이티브 메서드에 전달하면 IE 8 이하에서는 실패합니다. 아무도 신경 쓰지 않을 수도 있지만 일부는 그럴 수도 있습니다. ;-) 아, 지원하지 않는 getElementsByClassName을 하거나,하지만 querySelectorAll('.myClass')작동합니다. 반복자가 NodeList API에 추가되기를 기다리고 있습니다. :-(
RobG 2014-06-17

2
@Jer : 어떤 이유로 든 루프에서 벗어나려는 경우 부수적으로 Array.prototype.forEach그렇게 할 수 없습니다. 이 요구 사항이 나중에 표준 for루프를 사용하거나 배열 개체를 사용하려는 경우 Array.prototype.every또는 Array.prototype.some(모든 / 일부는 IE8 이하에서 지원되지 않음)
Nope

1
@Ian 개체가 "배열과 유사"하려면 접합이 필요합니다. 여기에 로그를 비교 : jsbin.com/sigut/1/edit
데니스 Séguret

1
@Ian TBH "배열 형"의 정의는 매우 모호하며 용도에 따라 다릅니다. 때로는 splice그 정의에 포함하지 않지만 map, filter등 을 사용할 수 있도록 "배열과 유사"하고 싶을 때 포함합니다. 를 사용하는 간단한 반복 forEachsplice.
Denys Séguret 2014 년

11

작동해야합니다.

<html>
  <head>
    <style type="text/css">
    </style>
  </head>
  <body>
   <div class="myClass">Hello</div>
   <div class="myClass">Hello</div>

<script type="text/javascript">
    var arr = document.getElementsByClassName('myClass');
    console.log(arr);
    console.log(arr[0]);
    arr = [].slice.call(arr); //I have converted the HTML Collection an array
    arr.forEach(function(v,i,a) {
        console.log(v);
    });
</script>


<style type="text/css">
    .myClass {
    background-color: #FF0000;
}
</style>

  </body>
</html>

0

특정 클래스의 각 요소 ID에 액세스하려는 경우 다음을 수행 할 수 있습니다.

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