如何在JavaScript中删除DOM节点的所有子元素?

假设我有以下(丑陋的)HTML:

<p id="foo">
    <span>hello</span>
    <div>world</div>
</p>

然后我像这样获取我想要的节点

var myNode = document.getElementById("foo");

我怎么能删除foo的孩子,这样就<p id="foo"></p>是剩下的?

我能不能这样做:

myNode.childNodes = new Array();

或者我应该使用一些组合的removeElement?

我希望答案是直接的DOM;不过,如果你在jQuery中提供了一个dom专用的答案,会有额外的加分。


当前回答

刚刚看到有人在另一个问题中提到这个问题,我想我会添加一个我还没有看到的方法:

function clear(el) {
    el.parentNode.replaceChild(el.cloneNode(false), el);
}

var myNode = document.getElementById("foo");
clear(myNode);

clear函数获取元素并使用父节点将其自身替换为没有其子节点的副本。如果元素是稀疏的,则性能增益不大,但当元素有一堆节点时,性能增益就实现了。

其他回答

目前公认的答案是错误的innerHTML更慢(至少在IE和Chrome),正如m93a正确提到的。

Chrome和FF使用这种方法会显着更快(这将破坏附加的jquery数据):

var cNode = node.cloneNode(false);
node.parentNode.replaceChild(cNode, node);

FF和Chrome远远排在第二,IE最快:

node.innerHTML = '';

InnerHTML不会破坏你的事件处理程序或打破jquery引用,它也建议作为一个解决方案在这里: https://developer.mozilla.org/en-US/docs/Web/API/Element.innerHTML。

最快的DOM操作方法(仍然比前两个慢)是范围移除,但是直到IE9才支持范围。

var range = document.createRange();
range.selectNodeContents(node);
range.deleteContents();

上面提到的其他方法看起来差不多,但比innerHTML慢很多,除了jquery(1.1.1和3.1.1),它比其他任何方法都要慢得多:

$(node).empty();

证据:

http://jsperf.com/innerhtml-vs-removechild/167 http://jsperf.com/innerhtml-vs-removechild/300 https://jsperf.com/remove-all-child-elements-of-a-dom-node-in-javascript (重新启动jsperf的新url,因为编辑旧url不工作)

Jsperf的“per-test-loop”通常被理解为“per-iteration”,只有第一次迭代需要删除节点,所以结果是没有意义的,在发布的时候,这个线程中的测试设置不正确。

使用elm.replaceChildren()。

它是实验性的,没有广泛的支持,但当不带参数执行时,它会做你所要求的,而且它比遍历每个子节点并删除它更有效。如前所述,用空字符串替换innerHTML将需要浏览器进行HTML解析。

MDN文档

它现在得到了广泛的支持

如果你想清空整个父DOM,那么很简单…

只需使用.empty()

函数removeAll() { $(' #父母')空虚(); } < script src = " https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js " > < /脚本> <按钮onclick = " removeAll ()>删除parent</button的所有元素 < div id = "父" > 标题< h3 > < / h3 > 儿童1 < p > < / p > 儿童2 < p > < / p > 孩子< p > 3 < / p > < / div >

使用range循环对我来说是最自然的:

for (var child of node.childNodes) {
    child.remove();
}

根据我在Chrome和Firefox中的测量,它要慢1.3倍左右。在正常情况下,这或许无关紧要。

用jQuery:

$("#foo").find("*").remove();