children 与 childNodes 区别

DOM 中 children 和 childNodes 属性的区别与使用场景

问题

childrenchildNodes 都能获取子节点,它们有什么区别?

解答

基本区别

// HTML 结构
// <div id="parent">
//   文本内容
//   <span>子元素1</span>
//   <!-- 注释 -->
//   <p>子元素2</p>
// </div>

const parent = document.getElementById('parent');

// childNodes: 返回所有子节点(包括文本、注释、元素)
console.log(parent.childNodes);
// NodeList(7) [text, span, text, comment, text, p, text]

// children: 只返回元素节点
console.log(parent.children);
// HTMLCollection(2) [span, p]

完整示例

<!DOCTYPE html>
<html>
<body>
  <div id="parent">
    文本内容
    <span>子元素1</span>
    <!-- 这是注释 -->
    <p>子元素2</p>
  </div>

  <script>
    const parent = document.getElementById('parent');

    // childNodes 包含所有节点类型
    console.log('childNodes 数量:', parent.childNodes.length); // 7
    parent.childNodes.forEach(node => {
      console.log(`类型: ${node.nodeType}, 名称: ${node.nodeName}`);
    });
    // 类型: 3, 名称: #text (文本节点)
    // 类型: 1, 名称: SPAN (元素节点)
    // 类型: 3, 名称: #text
    // 类型: 8, 名称: #comment (注释节点)
    // 类型: 3, 名称: #text
    // 类型: 1, 名称: P
    // 类型: 3, 名称: #text

    // children 只包含元素节点
    console.log('children 数量:', parent.children.length); // 2
    Array.from(parent.children).forEach(el => {
      console.log(`标签: ${el.tagName}`);
    });
    // 标签: SPAN
    // 标签: P
  </script>
</body>
</html>

返回类型对比

const parent = document.getElementById('parent');

// childNodes 返回 NodeList
console.log(parent.childNodes instanceof NodeList); // true
// NodeList 有 forEach 方法

// children 返回 HTMLCollection
console.log(parent.children instanceof HTMLCollection); // true
// HTMLCollection 没有 forEach,需要转换
Array.from(parent.children).forEach(el => {
  // 处理元素
});

节点类型常量

Node.ELEMENT_NODE    // 1 - 元素节点
Node.TEXT_NODE       // 3 - 文本节点
Node.COMMENT_NODE    // 8 - 注释节点

// 用 childNodes 筛选元素节点
const elements = Array.from(parent.childNodes).filter(
  node => node.nodeType === Node.ELEMENT_NODE
);
// 等价于 parent.children

关键点

  • childNodes 返回 NodeList,包含所有子节点(元素、文本、注释)
  • children 返回 HTMLCollection,只包含元素节点
  • HTML 中的换行和空格会产生文本节点,所以 childNodes.length 通常比预期大
  • NodeListforEach 方法,HTMLCollection 没有
  • 只需要操作元素时用 children,需要处理所有节点时用 childNodes