NodeList

この記事は編集レビューを必要としています。ぜひご協力ください

この翻訳は不完全です。英語から この記事を翻訳 してください。

NodeList オブジェクトは Node.childNodesdocument.querySelectorAll などのメソッドから返されるノードのコレクションを表します。

プロパティ

length
NodeList に含まれるノードの数

メソッド

item ( idx )
インデックスで指定した要素、もしくはインデックスが範囲外の場合は null を返します。範囲外の場合に  undefined を返す nodeList[idx] の代わりにこのメソッドを使うことができます。

説明

生きたコレクションとしての側面

NodeList は DOM の変化を反映する、生きたコレクションになっていることがあります。 Node.childNodes もその一つです。

var parent = document.getElementById('parent');
var child_nodes = parent.childNodes;
console.log(child_nodes.length); // "2" だったものが
parent.appendChild(document.createElement('div'));
console.log(child_nodes.length); // "3" になる

一方で、DOM の変化を一切反映しない静的なコレクションになっていることもあります。例えば document.querySelectorAll は静的な NodeList を返します。

NodeList の要素を列挙したり、要素の数をキャッシュするときには、この違いに注意した方がよいでしょう。

なぜ NodeList は Array ではないのか

NodeList は配列と似た使い方をすることが多く、 Array.prototype のメソッドを使いたくなりますが、 NodeList はおなじみの Array メソッドを一切備えていません。

JavaScript は Array などのビルトインオブジェクトと NodeLIst などのホストオブジェクトのどちらにもプロトタイプベースの継承メカニズムを使います。 Array のインスタンスが forEach や map などのメソッドを備えているのは、以下のようなプロトタイプチェーンになっているからです。

myArray --> Array.prototype --> Object.prototype --> null (オブジェクトのプロトタイプチェーンは Object.getPrototypeOf を繰り返し呼ぶことで調べることができます)

forEach や map は Array.prototype オブジェクト自身が持つプロパティです。

一方 NodeList のプロトタイプチェーンは次のようになっています。

myNodeList --> NodeList.prototype --> Object.prototype --> null

NodeList.prototype には item メソッドがありますが、 Array.prototype のメソッドは含まれていないため、これらを NodeLists で使うことはできないのです。

回避策

まず、 Array.prototype のメソッドを NodeList.prototype に追加する方法があります。ただし DOM の拡張は危険なことであり、特に古い Internet Explorer (6, 7, 8) の挙動には注意が必要です

var arrayMethods = Object.getOwnPropertyNames( Array.prototype );

arrayMethods.forEach( attachArrayMethodsToNodeList );

function attachArrayMethodsToNodeList(methodName)
{
  if(methodName !== "length") {
    NodeList.prototype[methodName] = Array.prototype[methodName];
  }
};
 
var divs = document.getElementsByTagName( 'div' );
var firstDiv = divs[ 0 ];

firstDiv.childNodes.forEach(function( divChild ){
  divChild.parentNode.style.color = '#0F0';
});

もう一つの方法では DOM を拡張しません。

var forEach = Array.prototype.forEach;

var divs = document.getElementsByTagName( 'div' );
var firstDiv = divs[ 0 ];

forEach.call(firstDiv.childNodes, function( divChild ){
  divChild.parentNode.style.color = '#0F0';
});

この方法ではホストオブジェクト (NodeList など) を this としてネイティブメソッド (forEach など) に渡していますが、全てのブラウザで動くことが保証されているわけではなく、動かないケースもあることが知られています。

It's possible to loop over the items in a NodeList using:

for (var i = 0; i < myNodeList.length; ++i) {
  var item = myNodeList[i];  // Calling myNodeList.item(i) isn't necessary in JavaScript
}

Don't be tempted to use for...in or for each...in to enumerate the items in the list, since that will also enumerate the length and item properties of the NodeList and cause errors if your script assumes it only has to deal with element objects. Also, for..in is not guaranteed to visit the properties in any particular order.

for...of loops will loop over NodeList objects correctly, in browsers that support for...of (like Firefox 13 and later):

var list = document.querySelectorAll( 'input[type=checkbox]' );
for (var item of list) {
  item.checked = true;
}

 NodeList を Array に変換する

NodeList の中身を慣れ親しんだ Array のメソッドで扱いたいこともあるでしょう。こうすると NodeList オブジェクトを Array に変換できます。

var div_list = document.querySelectorAll('div'); // returns NodeList
var div_array = Array.prototype.slice.call(div_list); // converts NodeList to Array

Spread operator をサポートするブラウザではこれを使うこともできます。

var div_list = document.querySelectorAll('div'); // returns NodeList
var div_array = [...div_list]; // converts NodeList to Array

もしくは Array.from() メソッドを使ってもよいでしょう。

var div_list = document.querySelectorAll('div'); // returns NodeList
var div_array = Array.from(div_list); // converts NodeList to Array

Another possibility is to use Object.keys() and Array.prototype.forEach() (for which polyfills are available):

var div_list = document.querySelectorAll('div'); // returns NodeList
Object.keys(div_list).forEach(function(key) {
  console.log(div_list[key]);
})

仕様

仕様書 策定状況 コメント
DOM
NodeList の定義
現行の標準  
DOM4
NodeList の定義
勧告  
Document Object Model (DOM) Level 3 Core Specification
NodeList の定義
勧告  
Document Object Model (DOM) Level 2 Core Specification
NodeList の定義
勧告  
Document Object Model (DOM) Level 1 Specification
NodeList の定義
勧告 Initial definition.

ドキュメントのタグと貢献者

 このページの貢献者: unarist, fscholz
 最終更新者: unarist,