HTMLCollectionとNodeListはともに配列風のオブジェクトですが、挙動が若干異なります。
今回は、HTMLCollectionとNodeListの違いについて解説していきます。
HTMLCollection
HTMLCollectionは、以下のようなメソッドで取得できる配列風のオブジェクトです。
document.getElementsByClassName()
document.getElementsByTagName()
以下のHTMLとJavaScriptで挙動を確認してみましょう。
<ul id="list">
<li class="item">テキスト</li>
<li class="item">テキスト</li>
<li class="item">テキスト</li>
<li class="item">テキスト</li>
</ul>
getElementsByClassName
で要素を取得してconsole.log
で中身を見れば、HTMLCollectionと出力されます。
const item = document.getElementsByClassName('item');
console.log(item); // => HTMLCollection
NodeList
NodeListは、以下のようなメソッドで取得できる、ノードの集合です。
document.querySelectorAll()
先ほどのHTMLにあるitemクラスの要素をquerySelectorAll
で取得してconsole.logで中身を見ると、NodeListと出力されます。
const item = document.querySelectorAll('.item');
console.log(item); // => NodeList
次に、HTML CollectionとNodeListの違いを解説していきます。
HTMLCollectionとNodeListの違い
HTMLCollectionとNodeListでは、要素の増減後の挙動とメソッドが異なります。
HTMLCollectionは動的、NodeListは静的
HTMLCollectionは後から要素の数が増減しても、動的に反映されます。
<ul id="list">
<li class="item">テキスト</li>
<li class="item">テキスト</li>
<li class="item">テキスト</li>
<li class="item">テキスト</li>
</ul>
const item = document.getElementsByClassName('item');
console.log(item.length); // => 4
// 要素を追加
const newList = document.createElement('li');
newList.innerText = 'テキスト';
newList.classList.add('item');
const list = document.getElementById('list');
list.appendChild(newList);
console.log(item.length); // => 5
一方、NodeListは要素の数が変わっても、後からそれが反映されません。
const item = document.querySelectorAll('.item');
console.log(item.length); // => 4
// 要素を追加
const newList = document.createElement('li');
newList.innerText = 'テキスト';
newList.classList.add('item');
const list = document.getElementById('list');
list.appendChild(newList);
console.log(item.length); // => 4
DOM操作後の状態で要素を取得するには、DOM操作後に再度取得する必要があります。
メソッドが異なる
HTMLCollectionとNodeListでは使えるメソッドが異なります。
例えば、NodeListではforEachメソッドが使えますが、HTMLCollectionでは使えません。
以下はconsole.logでそれぞれ出力した結果です。
forEachメソッドが存在するのが確認できます。
ですので、以下のループ処理は問題なく動作します。
const item = document.querySelectorAll('.item');
// 動作する
item.forEach((value, index) => {
value.classList.add('new-class');
});
一方、こちらにはforEachメソッドが存在しません。
以下のコードはエラーになります。
const item = document.getElementsByClassName('item');
// エラーになる
item.forEach((value, index) => {
value.classList.add('new-class');
});
HTMLCollectionでforEachを使ったループ処理を行いたい場合は、以下のようにします。
const item = document.getElementsByClassName('item');
Array.prototype.forEach.call( item, (value, index) => {
value.classList.add('new-class');
});
//もしくは
[...item].forEach((value, index) => {
value.classList.add('new-class');
});
記述が簡単なので私は[...item]
(スプレッド構文)を使った方法を使っています。
参考リンク
それぞれの仕様や使えるメソッドなどは以下のリンクで確認してください。
HTMLCollection – Web API | MDN
まとめ
HTMLCollectionとNodeListは似たようなオブジェクトですが、挙動が若干異なります。
違いを知っておくことで、余計なトラブルを避けましょう。
その他の記事
JavaScriptでオリジナルの右クリックメニューを表示する方法
こんにちは。今回は、デフォルトの右クリックを無効化して、オリジナルの右クリックを実装する方法です。D…
素のJavaScriptだけでページのトップへ戻るボタン(jQueryなし)
こんにちは。今回はjQueryを使わずに、JavaScriptだけでページの一番上に戻るボタンを実装…