JavaScript

【JavaScript】getElementsByClassName() メソッドでハマった件

More than 1 year has passed since last update.

なぜ?

何気なくgetElementsByClassName()メソッドを利用して、
任意のクラス名を含む全ての要素を取得した後に、反復処理を行おうと思ったのですが、、、
あれ?動かない?

動作しなかったコード
var checkBoxes = document.getElementsByClassName("checkBox");
for(var key in checkBoxes){
    if(checkBoxes[key].classList.contains("checked")){
        checkBoxes[key].checked = true;
    }
}

盛大に勘違いしていたのですが、
getElementsByClassName()メソッドが返す値は配列だと思っていたら、実は違った!
getElementsByClassName()は、配列に似ていますが実際には配列ではないHTMLcollectionオブジェクトを返します。
配列ではないので、例えばforEachみたいな便利な配列メソッドを呼び出すことはできません。
また、 for/inを使用してHTMLCollectionを反復処理することはできません。
(※現在のブラウザ環境では動作するみたいです。)

自分の環境では、for/inを使用した反復処理は動作したのですが、
HTMLCollectionはclassListプロパティを持たないので、要素に紐付いたclass属性のリストを返すelement.classListが使用できませんでした。

解決策

Array.prototypeを利用する

配列に変換
var checkBoxes = document.getElementsByClassName("checkBox");
var array = Array.prototype.slice.call(checkBoxes);//配列に変換

上記のようにArray.prototypeを使い配列に変換することで、解決しました。

ちなみに
getElementsByClassName()は、Internet Explorer8以下、Firefox2以下のブラウザでは使えないそうです。

まとめ

  • getElementsByClassName()メソッドが返す値は配列ではなく、HTMLCollection
  • HTMLCollectionは配列系のメソッドが使用できない

普段、jQueryを使い慣れているせいなのか、
JavaScriptでDOM操作するとつまづくことが多い...
目指せ!脱jQuery化!