children と childNodes の違い

childrenchildNodes は、要素の子を取得するプロパティです。よく似ていますが、取得できるノードの種類が違います。

基本的な違い

<ul id="list">
  <li>項目1</li>
  <li>項目2</li>
  <li>項目3</li>
</ul>
const list = document.getElementById('list');

console.log(list.children.length);     // 3(li 要素のみ)
console.log(list.childNodes.length);   // 7(テキストノードも含む)

なぜ childNodes は 7 になるのか

HTML のインデントや改行は「テキストノード」として存在します。

<ul id="list">   <!-- 改行・空白がテキストノード -->
  <li>項目1</li> <!-- 改行・空白がテキストノード -->
  <li>項目2</li> <!-- 改行・空白がテキストノード -->
  <li>項目3</li> <!-- 改行・空白がテキストノード -->
</ul>

childNodes はテキストノード、コメントノードなどすべてを含みます。children は Element だけを返します。

比較表

プロパティ内容戻り値
childrenElement のみHTMLCollection
childNodes全ノードNodeList

実際に動かしてみよう

HTML
CSS
JavaScript
<div id="parent">
  テキスト
  <span>スパン1</span>
  <span>スパン2</span>
</div>
<button id="showChildren">children</button>
<button id="showChildNodes">childNodes</button>
<p id="result"></p>
const parent = document.getElementById('parent');
const result = document.getElementById('result');

document.getElementById('showChildren').addEventListener('click', () => {
  result.textContent = 'children: ' + parent.children.length + ' 個の Element';
});

document.getElementById('showChildNodes').addEventListener('click', () => {
  const types = [...parent.childNodes].map(n => n.nodeType);
  result.textContent = 'childNodes: ' + parent.childNodes.length + ' 個 (型: ' + types.join(',') + ')';
});

nodeType の値

1Element
3Text
8Comment

どちらを使うべきか

ほとんどの場合は children を使います。要素だけを扱いたいことが多いからです。

// 子要素をループ
for (const child of parent.children) {
  console.log(child.tagName);
}

// 子要素の数
console.log(parent.children.length);

// 最初の子要素
console.log(parent.children[0]);

テキストノードやコメントノードも含めて処理したいときだけ childNodes を使います。