【问题标题】:for...in loop not looping through all properties?for...in 循环没有遍历所有属性?
【发布时间】:2015-12-23 10:45:10
【问题描述】:

当我加载我的页面时,会创建一个 nodeList,它看起来像这样:

[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]

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

谢谢。

【问题讨论】:

  • 因为您在循环遍历集合时正在修改集合。假设您在集合[A, B, C] 中有三个元素。 for..in 循环内部将有一个索引器来跟踪当前元素。所以索引器在开始时是 0,它指向元素 A。然后删除第一个元素,第二个元素B 现在成为第一个元素。索引器现在高级并指向 1。现在索引 1 处的元素 C 已被删除。正如您可能看到的那样,索引 0 处的元素 B 未被触及并被跳过。

标签: javascript for-loop for-in-loop nodelist


【解决方案1】:

两件事。首先,在遍历数字索引时不要使用for ... in;使用普通的for 循环。那么你就不需要那个isNaN()检查了,而且它通常更安全。

第二个问题是当你删除一个孩子时,你改变了列表的长度。如果您删除孩子 0,那么曾经是孩子 1 的孩子会变成孩子 0。因此,您真正想要的是一个简单的while 循环:

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

或者,更简单:

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

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

videoTitlesElement.innerHTML = "";

【讨论】:

  • 更简单的情况几乎是正确的,但这里:.removeChild(firstChild) firstChild 是未定义的。
  • 谢谢!很好的解释。在我的情况下,“清除” .innerHTML 并不是最好的,而且我还读到一个一个地删除元素通常要快得多。
  • @aCodingN00b 我会很惊讶地发现,一个一个地删除节点比清除.innerHTML 更快。
  • @aCodingN00b 这个问题很老了,我不相信这些 cmets 中的大多数。
【解决方案2】:

正在迭代的列表 (videoTitlesElement.childNodes) 在迭代期间发生了变异。尝试遍历原始列表的副本:

var children = [].slice.call(videoTitlesElement.childNodes);

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

【讨论】:

  • 请注意,使用for..in 遍历数组是不受欢迎的。
【解决方案3】:

如果您查看您的结果,您会注意到您正在跳过每隔一个项目。

如果你把它想象成一个带有迭代器的for 循环,那么你每次都在递增你的迭代器,但是在再次递增之前从同一个集合中删除一个项目。这意味着当您第一次启动循环时位于索引1 的项目在删除数组中的第一项后位于索引0。因此,当您查看索引1 时,您已经跳过了该元素。这会一直持续到循环结束,因此您会错过每一个项目。

【讨论】:

    猜你喜欢
    • 2017-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    相关资源
    最近更新 更多