DOMおれおれAdvent Calendar 2015 – 13日目

2015-12-13

ノードと要素の違いに近いもので、NodeListとHTMLCollectionの違いというものもあります。

NodeList

document.querySelectorAll() の戻り値の、配列風オブジェクトです。普段使っているのがこちら。

HTMLCollection

対してこちらは何であるかと言うと、例えば document.forms がこれです。フォームを全て格納したやつですね。

HTMLCollectionもNodeListと同様、やはり配列風オブジェクトですが、加えて名前( idname )によるアクセスも可能です。

<form id="foo"></form>
<form id="bar"></form>
console.log(document.forms[0]);      // <form id="foo"></form>
console.log(document.forms[1]);      // <form id="bar"></form>
console.log(document.forms['foo']);  // <form id="foo"></form>
console.log(document.forms['bar']);  // <form id="bar"></form>

forms については過去記事をどうぞ。

HTMLCollectionの出番

以下の場合がHTMLCollectionになります。

  • document.anchors
  • document.forms
  • document.images
  • document.links
  • document.getElementsByClassName()
  • document.getElementsByTagName()
  • node.children

他にもあるかも。(※NSはあまり使わない気がするのであえて外しました。)

ちなみに node.childNodes は自動的に更新されるNodeListです。ややこし。

children vs childNodes はこちら。

違い

NodeListは静的でありHTMLCollectionは動的である、という説明が一般的かと思います。

querySelectorAll() であるクラスを持つ全ての要素を全て引っ張ってきた後、JSからの操作により文書内の該当要素が増減等しても、先程取得しておいた結果は変わりません。

// あらかじめ <div class="foo"></div> が三つある状態

var fooList = document.querySelectorAll('.foo');
console.log(fooList.length);  // => 3

var elNewFoo = document.createElement('div');
elNewFoo.classList.add('foo');
document.body.appendChild(elNewFoo);

console.log(fooList.length);  // => 3 (変化なし)

一方で getElementsByClassName() で得た結果は更新されるので、常に最新の状態になります。

// あらかじめ <div class="foo"></div> が三つある状態

var fooCollection = document.getElementsByClassName('foo');
console.log(fooCollection.length);  // => 3

var elNewFoo = document.createElement('div');
elNewFoo.classList.add('foo');
document.body.appendChild(elNewFoo);

console.log(fooCollection.length);  // => 4 (変化あり!)

参考