使用node.childNodes.forEach删除childNodes [英] removing childNodes using node.childNodes.forEach

查看:400
本文介绍了使用node.childNodes.forEach删除childNodes的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

传统上,在Javascript中删除节点子节点的建议方法是执行以下操作:

Traditionally, a suggested way of removing a node's children in Javascript is to do something like this:

while(node.firstChild) {
    node.removeChild(node.firstChild);
}

最近,我尝试使用内置的forEach删除所有节点的子节点()方法:

Recently, I attempted to remove all of a node's children using the built in forEach() method:

node.childNodes.forEach(child => {
    node.removeChild(child);
}

这没有按照我的预期运行。而不是删除所有子节点, forEach停止执行,留下节点剩余。我最不得不做的是使用Array.from:

This didn't function as I expected. Instead of removing all child nodes, the forEach stopped executing, leaving nodes leftover. What I ended up having to do was use Array.from:

Array.from(node.childNodes)

然后我可以用forEach删除节点。我之所以无法使用传统节点上面提到的方法是因为某些原因,一个孩子总是被遗忘,导致无限循环。

And then I could remove nodes with forEach. The reason I could not use the traditional method mentioned above is because for some reason, one child was always left behind, causing an infinite loop.

为什么childNodes.forEach方法不会删除所有节点我认为这会是什么?我误解了什么?

Why does the childNodes.forEach method not remove all the nodes as I thought it would? What am I misunderstanding?

推荐答案

node.childNodes 是一个现场收藏。当你删除项目从中,集合本身被修改(在迭代时实时)。尝试按原样迭代它,导致元素从集合中移除,并在迭代时向下移动到类似数组的结构中,导致您错过节点。

node.childNodes is a live collection. As you remove items from it, the collection itself is modified (live while you're iterating). Trying to iterate it as you are, causes elements to be removed from the collection and moved down in the array-like structure while you're iterating it, causing you to miss nodes.

例如,当您在集合中的第二个元素上调用 removeChild()时,该元素本身将从集合中删除。这导致第3个元素移动到第2个元素所在的集合中的位置。现在,您的循环移动到集合中的第3个元素。但是,这将跳过现在处于第二位置的元素,导致您永远不会删除它。

As an example, when you call removeChild() on the 2nd element in the collection, that element itself is then removed from the collection. That causes what was the 3rd element to be moved into the spot in the collection where the 2nd element was. Now, your loop moves on to the 3rd element in the collection. But, that will skip over the element that is now in the 2nd position causing you to never remove it.

这意味着迭代实际集合的唯一安全方法删除东西是向后遍历,因为从结尾删除东西不会导致其他元素改变它们在集合中的位置。从正面删除项目(这就是你正在做的事情)会导致项目在集合中移动。

That means the only safe way to iterate through the actual collection and remove things is with a backwards traversal because removing things form the end does not cause other elements to change their position in the collection. Removing items from the front (which is what you were doing) does cause items to move in the collection.

Array.from()将实时集合转换为静态数组,其中从DOM中删除项目时不会从数组中删除项目。

Array.from() converts the live collection to a static array where items are not removed from the array while deleting items from the DOM.

我有DOM的个人规则在我以任何方式修改DOM时,永远不要使用实时集合,因为在我尝试使用它时,实时集合被修改的危险性太高了。 Array.from()是一种非常简单的方法,可以获取静态且可以安全使用的实时集合的副本,即使在修改DOM时也是如此。

I have a personal rule of DOM development to NEVER use a live collection while I'm modifying the DOM in any way because the danger that the live collection gets modified while I'm trying to use it is too high. Array.from() is a very simple way to get a copy of a live collection that's static and is safe to work with, even as the DOM is being modified.

另一种删除它们的安全方法是使用此向后迭代,因为项目从实时收集的末尾删除了t导致任何项目在您尚未处理的集合中移动:

Another safe way to delete them all is with this backwards iteration because items are removed from the end of the live collection which doesn't cause any items to move in the collection that you haven't yet processed:

for (let i = node.childNodes.length - 1; i >= 0; i--) {
   node.removeChild(node.childNodes[i]);
}

但是,我通常发现这比转换为静态数组更麻烦你已经发现 Array.from()

But, I generally find this more cumbersome than just converting to a static array with Array.from() as you've already discovered.

这篇关于使用node.childNodes.forEach删除childNodes的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆