从 DOM 中移除 HTMLCollection 元素

新手上路,请多包涵

我有一个段落元素的集合。有些是空的,有些只包含空格,而有些则有内容:

 <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
<p></p>
<p> </p>
<p>    </p>
<p>&nbsp;</p>
<p> &nbsp;</p>

我正在使用 getElementsByTagName 来选择它们:

 var paragraphs = document.getElementsByTagName('p');

这将返回文档中的所有段落。我想删除所有这些,所以我想运行

for (var i = 0, len = paragraphs.length; i < len; i++) {
   paragraphs[i].remove();
}

但我得到 Uncaught TypeError: Cannot read property 'remove' of undefined 错误。我觉得这很奇怪,但我会尝试添加一个守卫,看看会发生什么:

 for (var i = 0, len = paragraphs.length; i < len; i++) {
   paragraphs[i] && paragraphs[i].remove();
}

没有错误,但并未删除所有元素。所以我再次运行它,它删除 了一些 以前没有删除的元素。我 再次 运行它, 最后 所有段落都从文档中删除。

我想知道我在这里遗漏了什么明显的细节。

问题演示

原文由 Marc Kline 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 982
2 个回答

问题是 paragraphs 是一个 实时列表。通过删除 p 元素,您还更改了该列表。一个简单的解决方法是以 相反的顺序 遍历列表:

 for (var i = paragraphs.length - 1; i >= 0; --i) {
  paragraphs[i].remove();
}

替代解决方案是创建一个 静态列表(非实时列表)。您可以通过以下任一方式执行此操作:

  • 将列表转换为 Array
   var paragraphs =
    Array.prototype.slice.call(document.getElementsByTagName('p'), 0);

   var paragraphs = document.querySelectorAll('p');

然后,您可以按常规顺序遍历列表(使用 for 循环):

 for (var i = 0; i < paragraphs.length; ++i) {
  paragraphs[i].remove();
}

或者(使用 for...of 循环):

 for (var paragraph of paragraphs) {
  paragraph.remove();
}

请注意 .remove 是一种相对较新的 DOM 方法,并非每个浏览器都支持。有关详细信息,请参阅 MDN 文档


为了说明这个问题,假设我们有一个包含三个元素的节点列表 paragraphs = [p0, p1, p2] 。那么当您遍历列表时会发生这种情况:

 i = 0, length = 3, paragraphs[0] == p0  => paragraphs = [p1, p2]
i = 1, length = 2, paragraphs[1] == p2  => paragraphs = [p1]
i = 2, length = 1, END

所以在这个例子中, p1 没有被删除,因为它被跳过了。

原文由 Felix Kling 发布,翻译遵循 CC BY-SA 3.0 许可协议

当您删除一个项目时,您的 HTMLCollection 的长度会发生变化。一种方法是使用 while 循环

while(paragraphs.length > 0) {
   paragraphs[0].remove();
}

原文由 aljgom 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题