JavaScript
childNodes is a property that includes all child nodes of an element, including text nodes and comment nodes.
childNodes [property]
childNodesは、特定の要素の子要素を含む NodeList(ノードリスト)を返すプロパティです。NodeListは、配列に似たオブジェクトで、インデックス番号でアクセスできるノードのリストを表します。
例えば、以下のような HTML要素があった場合に、 childNodesを使って子要素を取得することができます。
<div id="parent">
<p>First paragraph</p>
<p>Second paragraph</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
JavaScriptで childNodesを使って子要素を取得するには、以下のようにします。
const parent = document.getElementById('parent');
const cNodes = parent.childNodes;
この場合、parent変数には id属性が "parent" である div要素が割り当てられ、childNodes変数には parent要素の全ての子要素(p要素、ul要素など)が含まれる NodeListオブジェクトが割り当てられます。
First paragraph
Second paragraph
- Item 1
- Item 2
<div id="parent">
<p>First paragraph</p>
<p>Second paragraph</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
<script>
const parent = document.getElementById('parent');
const cNodes = parent.childNodes;
console.log(cNodes);
</script>
上記のように、HTMLと JavaScriptを用意してコンソール画面で確認してみました。結果は下図のとおりとなりました。
ただし、注意すべき点がいくつかあります。たとえば、childNodesはテキストノードを含むため、NodeListのインデックス番号を使って要素にアクセスする際には、不要なテキストノードを除外するために追加の処理が必要になることがあります。
また、childNodesは子要素を順番に取得するため、要素の並び順が重要な場合は、childrenプロパティを使う方が便利かもしれません。childrenは、要素の子要素のみを含む HTMLCollectionを返し、テキストノードを含みません。
childNodesを使って取得した NodeListには、以下のようなメソッドやプロパティがあります。
length
lengthプロパティは、NodeList内のノードの数を取得します。例えば、上記の例では、上図のコンソール画面にも表示されていますが、parent要素の子要素の数は 7 であるため、childNodes.lengthは 7 となります。
console.log(cNodes.length); // 7
item()
item()メソッドは、指定したインデックスに対応するノードを取得します。インデックスは 0 から始まり、length - 1 までの値を取ることができます。上記の例で考えると lengthが 7 なので、7 - 1 = 6 までの値となります。
console.log(cNodes.item(0)); // #text
console.log(cNodes.item(1)); // <p>First paragraph</p>
また、インデックスを省略することで、item()メソッドを呼び出すこともできます。この場合、0 が暗黙的に渡されます。
console.log(cNodes[0]); // #text
console.log(cNodes[1]); // <p>First paragraph</p>
forEach()
forEach()メソッドは、NodeList内の各ノードに対して指定したコールバック関数を実行します。
childNodes.forEach(child => {
console.log(child.nodeName);
});
// #text
// P
// #text
// P
// #text
// UL
// #text
for...ofループ
ES6以降のバージョンでは、for...ofループを使用してNodeList内の各ノードにアクセスすることができます。
for (const child of cNodes) {
console.log(child.nodeName);
}
// #text
// P
// #text
// P
// #text
// UL
// #text
childNodes は、要素内の全ての子ノード(テキストノード、コメントノード、要素ノード)を含むため、特定の要素だけを取得する場合は、childrenプロパティを使用した方が便利です。
const parent = document.getElementById('parent');
const cNodes = parent.children;
console.log(cNodes);
この場合、HTMLCollectionオブジェクトが割り当てられます。HTMLCollectionには forEach()メソッドはありませんが、for...ofループを使用して各要素にアクセスできます。
for (const child of cNodes) {
console.log(child.nodeName);
}
childNodesを使用する際に注意すべき点がいくつかあります。
テキストノードや空白文字
childNodesは、テキストノードや空白文字を含むため、要素の子要素のみを取得する場合は、以下のようにフィルタリングする必要があります。
// 要素ノードのみを取得
const elementNodes = [];
cNodes.forEach(child => {
if (child.nodeType === Node.ELEMENT_NODE) {
elementNodes.push(child);
}
});
console.log(elementNodes);
ライブなコレクション
childNodesは、ライブなコレクションであるため、要素の子要素が変更された場合、自動的に更新されます。
First paragraph
Second paragraph
<div id="parent2">
<p>First paragraph</p>
<p>Second paragraph</p>
</div>
<script>
const parent2 = document.querySelector('#parent2');
const children = parent2.childNodes;
console.log(children.length); // 5
// 要素を追加
const newP = document.createElement('p');
newP.textContent = 'New paragraph';
parent2.appendChild(newP);
console.log(children.length); // 6
</script>
この場合、要素を追加すると childNodesに自動的に追加され、lengthプロパティの値が 6 に更新されます。
要素を指定して取得する場合の代替方法
特定の要素の子要素のみを取得する場合は、querySelectorAll()メソッドを使用することもできます。
const parent = document.querySelector('#parent');
const children = parent.querySelectorAll(':scope > *');
console.log(children.length); // 3
この場合、querySelectorAll()メソッドには、:scope という擬似クラスを使用して、直接の子要素のみを取得しています。* は全ての要素を意味します。
パフォーマンスの問題
childNodesは、すべての子ノードを含むため、DOMツリーが大きい場合は、パフォーマンスの問題が生じる可能性があります。子要素が多い要素の childNodesプロパティにアクセスする場合、ブラウザは子要素をすべて走査する必要があります。したがって、childNodesを使用する前に、コードを最適化し、可能な限り効率的にすることが重要です。