前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库DOM Node 和 Element 区别
浏览浏览器DOM 与文档操作

DOM 中 Node 和 Element 的区别是什么?

Node 是 DOM 中所有节点类型的抽象基接口,Element 是它的一个子接口,只代表元素节点;二者在属性和方法上呈包含与扩展关系。

前端进阶之旅 · 一题精讲更新于 2026.09.05
浏览器#DOM 与文档操作
先看核心答案
理解线索

用 nodeType 理解继承层次

  1. Node 是抽象基类Document、Text、Comment、Element 都继承它
  2. Element 是子类型nodeType 为 1,扩展标签相关属性方法
  3. API 分层归属树操作在 Node 上,属性选择器在 Element 上

判断某个 API 可用性时,先确认对象 nodeType 是否为 1,再决定按 Node 还是 Element 处理。

核心回答

先记住这个答案

DOM 里的 Node 是抽象基接口,Document、Element、Text、Comment、DocumentFragment 等都继承自它,因此不存在一个“纯粹的 Node 对象”。Element 是 Node 的子接口,nodeType 为 1,只代表标签元素。Node 上定义了树结构通用能力,如 childNodes、parentNode、appendChild、textContent;Element 在此之上扩展了元素专属能力,如 id、className、getAttribute、querySelector、children。所以所有 Element 都是 Node,但文本节点、注释节点等 Node 不是 Element。

  • Node 是抽象基接口,Element 是其子接口
  • childNodes 含全部节点,children 只含元素
  • 文本注释是 Node 但不是 Element

继承层次决定 API 归属

Node 接口继承自 EventTarget,它是抽象类,页面上不会出现一个直接实例化的 Node。它承载的是“树中一员”的通用语义:parentNode、childNodes、firstChild、nextSibling、isConnected,以及 appendChild、insertBefore、removeChild、cloneNode、contains 等结构操作方法。nodeType 属性返回数字常量,ELEMENT_NODE 是 1、TEXT_NODE 是 3、COMMENT_NODE 是 8、DOCUMENT_NODE 是 9,这是区分节点种类的根本依据。

Element 在 Node 之上叠加了元素语义:tagName、id、className、classList、attributes、getAttribute、setAttribute、querySelector、matches、children 等。这些 API 只对标签有意义,所以不挂在 Node 上。同样地,文本节点的数据操作 data、splitText 挂在 CharacterData 上而不是 Node 上。浏览器这样分层,是为了让每个接口只承诺自己能兑现的能力,例如向文本节点 appendChild 会抛异常,因为它在结构上不能有子节点。

遍历子节点时过滤出真实元素

假设要统计一个评论列表容器里的评论条数,HTML 由模板渲染,子节点之间混有换行文本和开发者留下的注释。如果用 container.childNodes.length,结果是包含空白文本节点和注释的总数,明显偏大。正确决策是改用 container.children.length,它返回 HTMLCollection,只包含 Element 子节点;或者遍历 childNodes 时用 node.nodeType === 1 过滤。这样得到的就是真实评论元素数。

之所以这样处理,是因为 HTML 源码里的换行和缩进会被解析成文本节点,它们在 DOM 树里占据位置但不对应任何标签。childNodes 的设计目标是完整反映树的结构,包括文本与注释,因此它是 NodeList;children 则是 Element 视角的快捷过滤结果。反过来,如果业务需要读取或修改元素之间的文字,就必须回到 childNodes,因为 children 会把文本节点整个隐藏掉。

按 Element 假设处理 Node 时容易失效的条件

常见失效点是拿到一个类型标注为 Node 的值就直接调用元素方法。例如遍历 childNodes 时对每项调用 getAttribute 或 classList,一旦遇到文本节点就会抛 TypeError,因为这些方法不存在于 Node 上。另一个边界是 parentNode 与 parentElement 的差异:当父级是 Document 时,parentNode 有值而 parentElement 返回 null,按元素处理会漏判。还有 nextSibling 可能返回文本节点,而 nextElementSibling 保证返回元素或 null。

对应的防御手段是先用 nodeType 或 instanceof Element 收窄类型,再访问元素专属 API;TypeScript 项目中可以用类型谓词封装 isElement 函数。代价是多一层判断和略冗长的代码,但换来的是对注释、文本、文档节点混在树中时的健壮性。需要注意 instanceof 在跨 iframe 场景会失败,因为不同窗口有各自的 Element 构造函数,此时用 nodeType === 1 更可靠,这是跨文档判断的边界。

回答前,多想一步

容易答错的地方

认为 Node 就是元素节点
Node 是抽象基接口,文本、注释、文档、属性节点都是 Node 但不是元素。把 childNodes 的结果当作元素集合直接读 id 会出错,必须先用 nodeType === 1 过滤或改用 children。
认为 children 和 childNodes 只是名字不同
children 只含元素节点,childNodes 含元素、文本、注释全部子节点。HTML 中的换行缩进会产生文本节点,二者长度常常不等,混用会导致统计或下标定位错误。
试着用自己的话回答

面试官还会怎么问?

文本节点能用 textContent 之外的什么属性读写内容?

文本节点继承自 CharacterData,可用 data 或 nodeValue 读写文本内容。对元素节点而言 nodeValue 是 null,这也是 Node 基类属性在部分子类型上不适用的典型例子。

querySelector 返回的可能是非元素节点吗?

不会。querySelector 用 CSS 选择器匹配,只可能命中 Element,找不到时返回 null。而 getRootNode、parentNode 这类 Node 层 API 则可能返回 Document 或文本等非元素节点。

为什么向文本节点 appendChild 会抛异常?

Node 基类声明了 appendChild,但不是所有节点类型都能有子节点。文本、注释这类 CharacterData 节点没有容纳子节点的结构,调用时会抛出 DOM 异常,这是基类能力在子接口上不适用的边界。

从一道题,走向一组知识

把知识连起来

DOM 与文档操作

parentNode.children 和 parentNode.childNodes 在遍历子节点时有什么区别?

children 只含 Element、childNodes 含全部 Node,正是 Node 与 Element 差异在遍历上的直接体现。

DOM 与文档操作

firstChild 和 firstElementChild 有何不同?

firstChild 返回任意 Node、firstElementChild 只返回 Element,可继续巩固按节点类型选择 API 的判断。

参考资料

  • Node

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 继承层次决定 API 归属
  3. 遍历子节点时过滤出真实元素
  4. 按 Element 假设处理 Node 时容易失效的条件
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑