Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用node.childNodes.forEach删除childNodes_Javascript_Dom_Ecmascript 6_Nodelist - Fatal编程技术网

Javascript 使用node.childNodes.forEach删除childNodes

Javascript 使用node.childNodes.forEach删除childNodes,javascript,dom,ecmascript-6,nodelist,Javascript,Dom,Ecmascript 6,Nodelist,传统上,在Javascript中删除节点子节点的建议方法是执行以下操作: while(node.firstChild) { node.removeChild(node.firstChild); } 最近,我尝试使用内置的forEach()方法删除节点的所有子节点: 这并没有像我预期的那样起作用。forEach不再删除所有子节点,而是停止执行,留下剩余节点。最后我不得不使用Array.from: Array.from(node.childNodes) 然后我可以用forEach删除节点

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

while(node.firstChild) {
    node.removeChild(node.firstChild);
}
最近,我尝试使用内置的forEach()方法删除节点的所有子节点:

这并没有像我预期的那样起作用。forEach不再删除所有子节点,而是停止执行,留下剩余节点。最后我不得不使用Array.from:

Array.from(node.childNodes)
然后我可以用forEach删除节点。我之所以不能使用上面提到的传统方法,是因为出于某种原因,总是有一个孩子落在后面,造成了一个无限循环


为什么childNodes.forEach方法不像我想象的那样删除所有节点?我误解了什么?

node.childNodes
是一个实时集合。当您从集合中删除项时,集合本身将被修改(在迭代时处于活动状态)。尝试按原样对其进行迭代会导致元素从集合中删除,并在迭代时在类似数组的结构中向下移动,从而导致丢失节点

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

这意味着遍历实际集合并删除内容的唯一安全方法是向后遍历,因为从末尾删除内容不会导致其他元素更改其在集合中的位置。从前面移除项目(这是您正在做的)会导致项目在集合中移动

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

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


另一种安全的删除方法是使用此向后迭代,因为项目将从live collection的末尾删除,这不会导致任何项目在您尚未处理的集合中移动:

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

但是,我通常觉得这比您已经发现的使用
array.from()
转换为静态数组更麻烦。

node.childNodes
是一个实时集合。当您从集合中删除项时,集合本身将被修改(在迭代时处于活动状态)。尝试按原样对其进行迭代会导致元素从集合中删除,并在迭代时在类似数组的结构中向下移动,从而导致丢失节点

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

这意味着遍历实际集合并删除内容的唯一安全方法是向后遍历,因为从末尾删除内容不会导致其他元素更改其在集合中的位置。从前面移除项目(这是您正在做的)会导致项目在集合中移动

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

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


另一种安全的删除方法是使用此向后迭代,因为项目将从live collection的末尾删除,这不会导致任何项目在您尚未处理的集合中移动:

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

但是,我通常认为这比您已经发现的使用
array.from()
转换为静态数组更麻烦。

node.childNodes
是一个活动的集合,因此当您从forEach中的
node
移除子节点时,您会弄乱迭代器


node.childNodes
是一个活动的集合,因此当您从forEach中的
node
中删除子节点时,您会弄乱迭代器


您看到结果中的模式了吗?想想在每次迭代中节点列表会发生什么。术语“内置”指的是ECMAScript的特性,主机提供的任何东西都是主机方法。因此节点列表实例的forEach方法不是“内置的”,而是一个宿主方法你看到结果中的模式了吗?想想在每次迭代中节点列表会发生什么。术语“内置”指的是ECMAScript的特性,主机提供的任何东西都是主机方法。因此节点列表实例的forEach方法不是“内置的”,而是一个宿主方法我明白了,谢谢你花时间解释。@m.chiang-DOM的设计师们到底拥有什么,甚至可以为我们提供现场收藏,这对我来说是个谜。它们造成的麻烦比我想象的任何公用事业都要多。幸运的是,
queryselectoral()