此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。

View in English Always switch to English

Node

基线
广泛可用
*

自 2015年7月 起,此特性已在主流浏览器中得到支持,可在大多数设备和浏览器版本中正常使用。

* 此特性的某些部分的支持程度可能有所不同。

文档对象模型的 Node 接口是许多其他 DOM API 对象所基于的抽象基类,因此这些对象类型可以以类似的方式使用,并且常常可以互换。作为抽象类,不存在纯粹的 Node 对象。所有实现 Node 功能的对象都基于它的某个子类。最主要的是 Document、Element 和 DocumentFragment。

此外,每一种 DOM 节点都由基于 Node 的接口表示。其中包括 Attr、CharacterData(Text、Comment、CDATASection 和 ProcessingInstruction 都基于它)以及 DocumentType。

在某些情况下,基类 Node 接口的某一特性可能不适用于某个子接口;此时,继承的节点可能返回 null 或抛出异常,具体取决于情形。例如,尝试向不能拥有子节点的节点类型添加子节点会抛出异常。

EventTarget Node

实例属性

除了下列属性外,Node 还从其父接口 EventTarget 继承属性。

Node.baseURI 只读

返回表示包含该 Node 的文档的基础 URL 的字符串。

Node.childNodes 只读

返回包含此节点所有子节点(包括元素、文本和注释)的实时 NodeList。NodeList 是实时的,意味着如果 Node 的子节点发生变化,NodeList 对象会自动更新。

Node.firstChild 只读

返回表示该节点第一个直接子节点的 Node,若没有子节点则为 null。

Node.isConnected 只读

布尔值,表示该 Node 是否(直接或间接)连接到上下文对象,例如常规 DOM 中的 Document 对象,或影子 DOM 中的 ShadowRoot。

Node.lastChild 只读

返回表示该节点最后一个直接子节点的 Node,若没有子节点则为 null。

Node.nextSibling 只读

返回表示树中下一个节点的 Node,若不存在则为 null。

Node.nodeName 只读

返回包含该 Node 名称的字符串。名称结构因节点类型而异。例如,HTMLElement 会包含对应标签的名称,如 HTMLAudioElement 为 'AUDIO';Text 节点为 '#text';Document 节点为 '#document'。

Node.nodeType 只读

返回表示节点类型的 unsigned short。可能的值有:

名称 值
ELEMENT_NODE 1
ATTRIBUTE_NODE 2
TEXT_NODE 3
CDATA_SECTION_NODE 4
PROCESSING_INSTRUCTION_NODE 7
COMMENT_NODE 8
DOCUMENT_NODE 9
DOCUMENT_TYPE_NODE 10
DOCUMENT_FRAGMENT_NODE 11
Node.nodeValue

获取或设置当前节点的值。

Node.ownerDocument 只读

返回此节点所属的 Document。如果节点本身就是文档,则返回 null。

Node.parentNode 只读

返回此节点的父 Node。如果不存在这样的节点——例如,此节点位于树的顶端,或不属于任何树——则此属性返回 null。

Node.parentElement 只读

返回此节点的父 Element。如果节点没有父节点,或父节点不是 Element,则此属性返回 null。

Node.previousSibling 只读

返回表示树中上一个节点的 Node,若不存在则为 null。

Node.textContent

获取或设置元素及其所有后代的文本内容。

实例方法

除了下列方法外,Node 还从其父接口 EventTarget 继承方法。

Node.appendChild()

将指定的 childNode 参数添加为当前节点的最后一个子节点。如果该参数引用了 DOM 树中已存在的节点,该节点会从其当前位置分离,并附加到新位置。

Node.cloneNode()

克隆一个 Node,并可选择是否克隆其全部内容。默认会克隆该节点的内容。

Node.compareDocumentPosition()

将当前节点的位置与任意其他文档中的另一个节点进行比较。

Node.contains()

返回 true 或 false,表示某个节点是否为调用节点的后代。

Node.getRootNode()

返回上下文对象的根,可选地在可用时包含影子根。

Node.hasChildNodes()

返回布尔值,表示该元素是否有任何子节点。

Node.insertBefore()

在指定父节点下,将一个 Node 插入为参考节点之前的子节点。

Node.isDefaultNamespace()

接受命名空间 URI 作为参数,若该命名空间是给定节点上的默认命名空间则返回 true,否则返回 false。

Node.isEqualNode()

返回布尔值,表示两个节点是否类型相同且所有定义性数据点都匹配。

Node.isSameNode()

返回布尔值,表示两个节点是否为同一个节点(即引用同一对象)。

Node.lookupPrefix()

返回包含给定命名空间 URI 的前缀的字符串(若存在),否则返回 null。当可能有多个前缀时,结果取决于实现。

Node.lookupNamespaceURI()

接受前缀并返回给定节点上与之关联的命名空间 URI(若找到),否则返回 null。为前缀传入 null 将返回默认命名空间。

Node.normalize()

清理此元素下的所有文本节点(合并相邻节点,移除空节点)。

Node.removeChild()

从当前元素移除一个子节点,该节点必须是当前节点的子节点。

Node.replaceChild()

用参数中给出的第二个节点替换当前节点的一个子 Node。

事件

selectstart

当用户在此节点中开始新的选区时触发。

示例

移除节点内嵌套的所有子节点

此函数会反复移除元素的第一个子节点,直到没有子节点为止。

js
function removeAllChildren(element) {
  while (element.firstChild) {
    element.removeChild(element.firstChild);
  }
}

使用此函数只需一次调用。下面我们清空文档的 body:

js
removeAllChildren(document.body);

另一种做法是将 textContent 设为空字符串:document.body.textContent = ""。

递归遍历子节点

以下函数会为根节点所包含的每个节点(包括根节点自身)递归调用回调函数:

js
function eachNode(rootNode, callback) {
  if (!callback) {
    const nodes = [];
    eachNode(rootNode, (node) => {
      nodes.push(node);
    });
    return nodes;
  }

  if (callback(rootNode) === false) {
    return false;
  }

  if (rootNode.hasChildNodes()) {
    for (const node of rootNode.childNodes) {
      if (eachNode(node, callback) === false) {
        return;
      }
    }
  }
}

该函数会为 rootNode 的每个后代节点(包括根节点自身)递归调用一个函数。

如果省略 callback,函数会改为返回一个 Array,其中包含 rootNode 及其内部的所有节点。

如果提供了 callback,并且调用时返回 false,则中止当前递归层级,函数在上一层父节点处恢复执行。这可用于在找到某个节点后中止循环(例如搜索包含特定字符串的文本节点)。

该函数有两个参数:

rootNode

将递归遍历其后代的 Node 对象。

callback 可选

可选的回调函数,只接收一个 Node 参数。如果省略,eachNode 会返回 rootNode 内每个节点(包括根节点自身)组成的 Array。

下面展示 eachNode() 函数的实际用法:在网页上搜索文本。

我们使用名为 grep 的包装函数来执行搜索:

js
function grep(parentNode, pattern) {
  let matches = [];
  let endScan = false;

  eachNode(parentNode, (node) => {
    if (endScan) {
      return false;
    }

    // 忽略非文本节点
    if (node.nodeType !== Node.TEXT_NODE) {
      return;
    }

    if (typeof pattern === "string" && node.textContent.includes(pattern)) {
      matches.push(node);
    } else if (pattern.test(node.textContent)) {
      if (!pattern.global) {
        endScan = true;
        matches = node;
      } else {
        matches.push(node);
      }
    }
  });

  return matches;
}

规范

规范
DOM
# interface-node

浏览器兼容性