for...in循环未遍历所有属性?

4
当我加载页面时,会创建一个节点列表,它看起来像这样:
[text, h4, text, span, br, input, br, span, br, input, br, span, br, input, br, span, br, input, br]

我创建了一个简单的for循环,遍历所有这些元素,并将它们从DOM中删除。 (所有元素都在<section>中)

以下是循环代码:

        for(element in videoTitlesElement.childNodes){
            if(!isNaN(element)){
                videoTitlesElement.removeChild(
                        videoTitlesElement.childNodes[element]);
            }
        }

但是,在循环结束时,nodeList 的样子就像这样:

[h4, span, input, span, input, span, input, span, input]

为什么并非所有元素都被删除了?

谢谢。


2
因为你在遍历集合时修改了它。假设你有一个集合 [A, B, C]for..in 循环内部将有一个索引器来跟踪当前元素。因此,在开始时,索引器为0,指向元素 A。然后你删除第一个元素,第二个元素 B 现在成为第一个。索引器现在被提升并指向1。现在移除索引1处的元素 C。正如你所看到的,索引0处的元素 B 未受影响并被跳过。 - Sani Huttunen
3个回答

12

两个问题。首先,在遍历数字索引时不要使用for ... in,应该使用普通的for循环。这样你就不需要那个isNaN()检查了,而且更加安全。

第二个问题是,当你删除一个子元素时,你改变了列表的长度。如果你删除了第一个子元素,那么原来的第二个子元素就成为了第一个子元素。因此,你真正需要的是一个简单的while循环:

while (videoTitlesElement.childNodes.length)
  videoTitlesElement.removeChild(videoTitlesElement.childNodes[0]);

或者更简单地说:

while (videoTitlesElement.firstChild)
  videoTitlesElement.removeChild(videoTitlesElement.firstChild);

我应该注意(假设您正在使用HTML DOM),通过简单地使用.innerHTML来清除元素的所有子节点会更容易:

我也应该注意(假设您正在使用HTML DOM),通过简单地使用.innerHTML来清除元素的所有子节点会更容易:

videoTitlesElement.innerHTML = "";

简单的情况几乎正确,但是这里:.removeChild(firstChild)中的firstChild未定义。 - pawel
@Pointy https://dev59.com/eG865IYBdhLWcg3wKLT6 - bool3max
@aCodingN00b 那个问题很老了,我不相信大多数评论。 - Pointy
@StriplingWarrior 我不确定我信任那个测试的原始版本;这是一件难以衡量的事情,因为很难避免在每次测试迭代后清除DOM并重新构建的成本。 - Pointy
@Pointy:说得好。我想性能差异无论如何都不太可能引起注意。 - StriplingWarrior
显示剩余2条评论

4
正在迭代的列表(videoTitlesElement.childNodes)在迭代过程中进行了修改。请尝试迭代原始列表的副本:
var children = [].slice.call(videoTitlesElement.childNodes);

for(element in children){
    if(!isNaN(element)){
         videoTitlesElement.removeChild(videoTitlesElement.childNodes[element]);
    }
}

1
请注意,使用 for..in 迭代数组是不被鼓励的。 - pawel

3
如果你查看结果,你会发现你跳过了每一个第二个项目。
如果你把这个想象成一个带有迭代器的for循环,你每次都会增加迭代器,但在增加之前会从相同的集合中删除一个项目。这意味着当你第一次开始循环时,位于索引1的项在删除数组中的第一个项后变为索引0。因此,当你去查看索引1时,你已经跳过了那个元素。这将持续到循环结束,所以你错过了每一个第二个项目。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接