前言
在 Web 开发中,我们每天都在操作 DOM。但你是否注意到,几乎所有的 DOM 对象(div、p、comment 甚至 document)都拥有一套通用的属性和方法?这是因为它们都继承自 Node 接口。理解 Node,是深入掌握原生 JavaScript 操控网页的关键。
一、 Node 节点核心属性
Node 接口提供了一组标准属性,用于识别节点的身份和内容。
1. 节点类型标识
-
nodeType:通过数字常量快速判断节点身份。- 1 (
Node.ELEMENT_NODE): 元素节点,如<div>。 - 3 (
Node.TEXT_NODE): 文本节点,包含空格和换行。 - 8 (
Node.COMMENT_NODE): 注释节点。 - 9 (
Node.DOCUMENT_NODE): 根节点document。
- 1 (
-
nodeName:对于元素节点,返回大写的标签名(如"DIV")。 -
nodeValue:读写文本值,注意点——只有文本、注释、属性节点可以读写此值;对于元素节点,该值恒为null。
二、 节点关系网:纵横遍历
通过这些属性,你可以像在地图上移动一样在 DOM 树中穿梭。
| 属性 | 描述 |
|---|---|
parentNode | 指向父节点 |
childNodes | 实时的子节点集合(包含文本和注释) |
firstChild / lastChild | 第一个和最后一个子节点 |
previousSibling / nextSibling | 前一个和后一个兄弟节点 |
ownerDocument | 直接指向顶级的 document 对象 |
💡 避坑指南:
childNodes是包含“空白文本节点”的。如果你只想获取标签元素,请使用children、firstElementChild等 Element 专有的属性。
三、 节点操作方法:增删改查
Node 接口提供的方法是所有 DOM 变动的基石。
1. 插入与替换
appendChild(node):将节点添加到子节点列表的末尾。insertBefore(newNode, refNode):在参考节点前插入。如果refNode为null,效果等同于appendChild。replaceChild(newNode, oldNode):替换旧节点。
2. 移除与克隆
-
removeChild(node):移除子节点。注意: 节点并没有被销毁,只是从 DOM 树中剥离,方法会返回该节点的引用。 -
cloneNode(deep):复制节点true(深拷贝):复制节点及其内部所有子树。false(浅拷贝):只复制节点本身及其属性。
3. 特殊工具方法
normalize():清理工。它会合并相邻的文本节点,并删除空的文本节点。在复杂的 DOM 手动操作后非常有用。contains(node):判断传入的节点是否是当前节点的后代(包括自身),常用于点击外部关闭弹窗的逻辑。
四、 面试常见问答
Q1:NodeList 和 HTMLCollection 有什么区别?
参考回答:
NodeList(由childNodes返回)可以包含任何节点类型。HTMLCollection(由children返回)仅包含元素节点(Element)。- 两者通常都是实时的(Live) ,即 DOM 改变,集合会自动更新(但
querySelectorAll返回的是静态的)。
Q2:如何判断一个节点是否含有子节点?
参考回答:
除了检查 childNodes.length,更优雅的方法是调用 node.hasChildNodes(),它返回一个布尔值。
Q3:cloneNode 会复制绑定在元素上的事件吗?
参考回答:
不会。 cloneNode 只复制 HTML 属性(包括 inline 事件如 onclick="..."),但不会复制通过 addEventListener 绑定的 JavaScript 事件。