前置き
NodeList
NodeList インスタンスは、メンバがノード・オブジェクトである配列のようなオブジェクトです。以下のメソッドを使用して、NodeList インスタンスを取得できます。
- Node.childNodes
- document.querySelectorAll()等ノード検索メソッド
document.body.childNodes instanceof NodeList // true
NodeList インスタンスは配列によく似ており、length プロパティや forEach メソッドを使用できます。ただし、配列ではないので、pop や push などの配列固有のメソッドを使用することはできません。
var children = document.body.childNodes;
Array.isArray(children) // false
children.length // 34
children.forEach(console.log)
NodeList インスタンスが array メソッドを使用する場合は、実際の配列に変換できます。
var children = document.body.childNodes;
var nodeArr = Array.prototype.slice.call(children);
forループも使えます。
var children = document.body.childNodes;
for (var i = 0; i < children.length; i++) {
var item = children[i];
}
NodeList インスタンスは動的コレクションまたは静的コレクションであることに注意してください。動的コレクションは生きているコレクションで、DOM が関連するノードを削除または追加すると、即座に NodeList インスタンスに反映されます。
Node.childNodes だけが動的なコレクションを返し、他のすべての NodeList は静的なコレクションです。
var children = document.body.childNodes;
children.length // 18
document.body.appendChild(document.createElement('p'));
children.length // 19
NodeList.prototype.length
length 属性は、NodeList インスタンスに含まれるノードの数を返します。
document.querySelectorAll('xxx').length
// 0
NodeList.prototype.forEach()
forEach メソッドは、NodeList のすべてのメンバを繰り返し処理するために使用します。この関数はコールバック関数を引数として取り、走査の各ラウンドで 1 回実行され、配列インスタンスの forEach メソッドとまったく同じ方法で使用されます。
var children = document.body.childNodes;
children.forEach(function f(item, i, list) {
// ...
}, this);
コールバック関数fの3つの引数は、順に、現在のメンバー、位置、現在のNodeListインスタンスです。forEachメソッドの2番目の引数は、コールバック関数内で thisをバインドするために使用されますが、省略可能です。
NodeList.prototype.item()
item メソッドは、メンバの位置を示す整数値を引数として受け入れ、その位置のメンバを返します。
document.body.childNodes.item(0)//最初のメンバを返す。
配列のようなオブジェクトはすべて、角括弧演算子を使ってメンバを削除することができます。一般的に、角括弧演算子は item メソッドなしで使われます。
document.body.childNodes[0]
NodeList.prototype.keys(), NodeList.prototype.values(), NodeList.prototype.entries()
3つのメソッドはすべてES6トラバーサーオブジェクトを返し、それをfor....ループで走査し、各メンバーの情報を取得します。違いは、keys() はキー名のイテレータを返し、 values() はキー値のイテレータを返し、 entries() はキー名とキー値の両方の情報を含むイテレータを返すことです。
var children = document.body.childNodes;
for (var key of children.keys()) {
console.log(key);
}
// 0
// 1
// 2
// ...
for (var value of children.values()) {
console.log(value);
}
// #text
// <script>
// ...
for (var entry of children.entries()) {
console.log(entry);
}
// Array [ 0, #text ]
// Array [ 1, <script> ]
// ...
HTMLCollection
HTMLCollection はノード・オブジェクトのコレクションで、要素ノードのみを含むことができます。
その戻り値は配列のようなオブジェクトですが、NodeList インターフェースとは異なり、HTMLCollection は forEach メソッドを持たず、for ループを使ってのみ走査することができます。
document.links instanceof HTMLCollection // true
HTMLCollection インスタンスは動的なコレクションで、ノードの変更はリアルタイムでコレクションに反映されます。
要素ノードに id 属性または name 属性がある場合、上記の HTMLCollection インスタンスは id 属性または name 属性を使用してノード要素を参照できます。対応するノードがない場合は null が返されます。
// HTML コードは以下の通りである。
// <img id="pic" src="http://.com/.jpg">
var pic = document.getElementById('pic');
document.images.pic === pic // true
HTMLCollection.prototype.length
length 属性は、HTMLCollection インスタンスが含むメンバの数を返します。
document.links.length // 18
HTMLCollection.prototype.item()
item メソッドは、メンバの位置を示す整数値をパラメータとして取り、その位置のメンバを返します。
itemこのメソッドは、メンバの位置を示す整数値を引数として受け入れ、その位置のメンバを返す
item(0) は、位置 0 のメンバを返すことを意味します。角括弧演算子も同じ目的を果たし、より便利に使用できるため、一般的には常に角括弧演算子が使用されます。
HTMLCollection.prototype.namedItem()
namedItem メソッドの引数は id 属性または name 属性の値を表す文字列で、対応する要素ノードを返します。対応するノードがない場合は、NULL が返されます。
// HTML コードは以下の通りである。
// <img id="pic" src="http://.com/.jpg">
var pic = document.getElementById('pic');
document.images.namedItem('pic') === pic // true
ParentNode
ParentNode インターフェースは、現在のノードが親ノードであることを示し、子ノードを処理するためのいくつかのメソッドを提供します。
現在のノードが親ノードの場合、ParentNode インターフェースと混合されます。子ノードを持つのは要素ノード、ドキュメントノード、ドキュメントフラグメントノードだけなので、この3種類のノードだけが ParentNode インターフェースを持ちます。
ParentNode.children
children 属性は、メンバが現在のノードの全ての要素の子である HTMLCollection インスタンスを返します。この属性は読み取り専用です。
ノードのすべての子要素を反復処理する例。
for (var i = 0; i < el.children.length; i++) {
// ...
}
children 属性は要素の子ノードのみを含み、他の型の子ノードは含みません。要素型の子ノードがない場合、返される HTMLCollection インスタンスの length 属性は 0 です。
HTMLCollectionは、DOMの変更をリアルタイムに反映する動的なコレクションです。
ParentNode.firstElementChild
firstElementChild プロパティは、現在のノードの最初の要素の子を返します。要素の子がない場合は、NULL が返されます。
document.firstElementChild.nodeName
// "HTML"
ドキュメント・ノードの最初の子要素は
ParentNode.lastElementChild
lastElementChild プロパティは、現在のノードの最後の子要素を返します。
document.lastElementChild.nodeName
// "HTML"
ParentNode.childElementCount
childElementCount 属性は、現在のノードの全ての要素の子の数を表す整数を返します。要素の子を含まない場合は 0 を返します。
document.body.childElementCount // 13
ParentNode.append(),ParentNode.prepend()
append メソッドは、1 つ以上の子ノードを現在のノードに追加します。
このメソッドは、要素の子ノードだけでなく、テキストの子ノードも追加できます。
var parent = document.body;
// 要素の子ノードを追加する
var p = document.createElement('p');
parent.append(p);
// テキストの子ノードを追加する
parent.append('Hello');
// 複数の要素の子ノードを追加する
var p1 = document.createElement('p');
var p2 = document.createElement('p');
parent.append(p1, p2);
// 要素の子ノードとテキストの子ノードを追加する
var p = document.createElement('p');
parent.append('Hello', p);
このメソッドには戻り値はありません。
prepend メソッドは、1 つ以上の子ノードを現在のノードに追加します。append メソッドとまったく同じように使用され、戻り値はありません。
ChildNode
ノードが親を持つ場合、そのノードは ChildNode インタフェースを持ちます。
ChildNode.remove()
remove メソッドは、現在のノードを親から削除するために使用します。
el.remove()
ChildNode.before(),ChildNode.after()
before メソッドは、現在のノードの前に 1 つ以上の兄弟ノードを挿入するために使用します。どちらも同じ親ノードを持ちます。
このメソッドは要素ノードだけでなく、テキスト・ノードも挿入できることに注意してください。
var p = document.createElement('p');
var p1 = document.createElement('p');
// 要素ノードを挿入する
el.before(p);
// テキスト・ノードを挿入する
el.before('Hello');
// 複数の要素ノードを挿入する
el.before(p, p1);
// 要素ノードとテキスト・ノードを挿入する
el.before(p, 'Hello');
after メソッドは、現在のノードの後に 1 つ以上の兄弟ノードを挿入するために使用します。使い方は before メソッドと同じです。
ChildNode.replaceWith()
replaceWith メソッドは、引数のノードを使用し、現在のノードを置き換えます。引数には、要素ノードまたはテキスト・ノードを指定できます。
var span = document.createElement('span');
el.replaceWith(span);
elノードはspanノードに置き換えられます。