节点从技术上说仍然被同一个文档所拥有,但文档中已经没有它的位置。 要移除节点而不是替换节点,可以使用 removeChild()方法。这个方法接收一个参数,即要移除
的节点。被移除的节点会被返回,如下面的例子所示:
// 删除第一个子节点
let formerFirstChild = someNode.removeChild(someNode.firstChild);
// 删除最后一个子节点
let formerLastChild = someNode.removeChild(someNode.lastChild);
与 replaceChild()方法一样,通过 removeChild()被移除的节点从技术上说仍然被同一个文档 所拥有,但文档中已经没有它的位置。
上面介绍的 4 个方法都用于操纵某个节点的子元素,也就是说使用它们之前必须先取得父节点(使 用前面介绍的 parentNode 属性)。并非所有节点类型都有子节点,如果在不支持子节点的节点上调用 这些方法,则会导致抛出错误。
4. 其他方法
所有节点类型还共享了两个方法。第一个是 cloneNode(),会返回与调用它的节点一模一样的节 点。cloneNode()方法接收一个布尔值参数,表示是否深复制。在传入 true 参数时,会进行深复制, 即复制节点及其整个子 DOM 树。如果传入 false,则只会复制调用该方法的节点。复制返回的节点属 于文档所有,但尚未指定父节点,所以可称为孤儿节点(orphan)。可以通过 appendChild()、 insertBefore()或 replaceChild()方法把孤儿节点添加到文档中。以下面的 HTML 片段为例:
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
如果 myList 保存着对这个
- 元素的引用,则下列代码展示了使用 cloneNode()方法的两种方式:
let deepList = myList.cloneNode(true);
alert(deepList.childNodes.length); // 3(IE9之前的版本)或7(其他浏览器) let shallowList = myList.cloneNode(false);
alert(shallowList.childNodes.length); // 0
在这个例子中,deepList 保存着 myList 的副本。这意味着 deepList 有 3 个列表项,每个列表 项又各自包含文本。变量 shallowList 则保存着 myList 的浅副本,因此没有子节点。 deepList.childNodes.length 的值会因 IE8 及更低版本和其他浏览器对空格的处理方式而不同。IE9 之前的版本不会为空格创建节点。
本节要介绍的最后一个方法是 normalize()。这个方法唯一的任务就是处理文档子树中的文本节 点。由于解析器实现的差异或 DOM 操作等原因,可能会出现并不包含文本的文本节点,或者文本节点之间互为同胞关系。在节点上调用 normalize()方法会检测这个节点的所有后代,从中搜索上述两种 情形。如果发现空文本节点,则将其删除;如果两个同胞节点是相邻的,则将其合并为一个文本节点。 这个方法将在本章后面进一步讨论。