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

2015-12-13

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

NodeList

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

HTMLCollection

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

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

1
2
<form id="foo"></form>
<form id="bar"></form>
1
2
3
4
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からの操作により文書内の該当要素が増減等しても、先程取得しておいた結果は変わりません。

1
2
3
4
5
6
7
8
9
10
// あらかじめ <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() で得た結果は更新されるので、常に最新の状態になります。

1
2
3
4
5
6
7
8
9
10
// あらかじめ <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 (変化あり!)

参考