跳到主要内容

说说有几种类型的 DOM 节点

面试速答(30 秒版 TL;DR)

  • “DOM 节点类型”通常指 Node.nodeType 这套枚举:规范里一共 12 种112)。
  • 但在 HTML 页面里你经常真实遇到的主要是:Document(9)DocumentType(10)Element(1)Text(3)Comment(8)DocumentFragment(11)
  • 面试回答建议分两层:先给“规范答案(12)”,再补充“常见答案(6)”,避免死背但不落坑。

心智模型:DOM 树上的每个东西都是 Node

你可以把 Node 理解为“树结构的统一抽象”。不同节点类型只是 Node 的不同实现(接口/子类型),所以它们都能通过 parentNodechildNodesappendChild 等一套共同 API 参与到“树”的增删改查。


规范里的 12 种 nodeType(重点看常见项)

节点类型nodeType常见于 HTML?例子/说明
ELEMENT_NODE1divspan 等元素节点
ATTRIBUTE_NODE2有但不常当“树节点”讲Attr(属性对象),多数情况下通过 getAttribute/attributes 访问,不作为子节点遍历
TEXT_NODE3元素内部的文本
CDATA_SECTION_NODE4XML 相关(HTML 中基本不用)
ENTITY_REFERENCE_NODE5历史/废弃(XML 相关)
ENTITY_NODE6历史/废弃(XML 相关)
PROCESSING_INSTRUCTION_NODE7XML 相关
COMMENT_NODE8<!-- comment -->
DOCUMENT_NODE9document
DOCUMENT_TYPE_NODE10<!doctype html> 对应的 document.doctype
DOCUMENT_FRAGMENT_NODE11DocumentFragment,常用于批量插入优化
NOTATION_NODE12历史/废弃(XML 相关)

最小可运行示例:用 nodeType 验证

const el = document.createElement("div");
el.textContent = "hi";

const text = el.firstChild; // Text
const comment = document.createComment("c");
const frag = document.createDocumentFragment();

console.log(el.nodeType, el.nodeName); // 1 "DIV"
console.log(text.nodeType, text.nodeName); // 3 "#text"
console.log(comment.nodeType, comment.nodeName); // 8 "#comment"
console.log(document.nodeType, document.nodeName); // 9 "#document"
console.log(document.doctype?.nodeType, document.doctype?.name); // 10 "html"
console.log(frag.nodeType, frag.nodeName); // 11 "#document-fragment"

常见追问

Q1:ElementNodeHTMLElement 有什么关系?

  • Node:最抽象的“节点”。
  • Element:元素节点的抽象类型(对应 nodeType = 1)。
  • HTMLElement:HTML 场景下的元素基类(div 对应 HTMLDivElement,继承链上通常会有 HTMLElement)。

Q2:为什么遍历子节点时经常要区分“元素”还是“节点”?

因为 childNodes 会包含文本节点、注释节点等(例如空白换行也可能是 Text),而 children 只包含元素节点;不区分就容易出现“多出来的 #text”导致逻辑错误。


易错点/坑

  • 把“DOM 节点类型”只回答成“元素、文本、注释”不算错,但不完整;建议补一句“规范枚举有 12 种,HTML 常见 6 种”。
  • 不要假设元素内部一定只有元素子节点:空白也可能形成 Text 节点(尤其是格式化后的 HTML)。

速记要点(可背诵)

  • 规范枚举 12 种;HTML 常用 6 种:9/10/1/3/8/11