【问题标题】:.forEach() stops after first iteration.forEach() 在第一次迭代后停止
【发布时间】:2020-02-02 22:05:24
【问题描述】:

一个简单的.forEach() 在第一次迭代后停止,具体取决于内容...

我的初始循环如下所示:

document.getElementsByClassName("app-form-to-js").forEach(function(node) {
    node.classList.remove("app-form-to-js");
    jsForms[node.id]=node.cloneNode(true);
    node.remove();
});

当第一个循环发生时,它并没有超出。
然后,经过一些调整,我设法让循环使用这段代码:

document.getElementsByClassName("app-form-to-js").forEach(function(node) {
    jsForms[node.id]=node.cloneNode(true);
    jsForms[node.id].classList.remove("app-form-to-js");
});

但是,当我在循环中使用 node.classList.remove("app-form-to-js");node.remove(); 时,
它总是在第一次迭代后停止。

如果我改变节点,为什么循环在第一次迭代后停止(所以它至少迭代一次)?

【问题讨论】:

  • document.getElementsByClassName 返回元素的实时集合。这实际上意味着它会随着您对 DOM 元素的变异而改变。您可能希望复制元素集合然后对其进行迭代。
  • document.getElementsByClassName(...).forEach is not a function ?
  • document.getElementsByClassName 不包含forEach 函数...
  • 尝试使用两个单独的 forEach 1. 用于 cloneNode,2nd 用于删除类
  • @Preciel 突变肯定是一个问题(或至少其中一个):node.classList.remove("app-form-to-js"); 执行此操作后 - 当前节点从列表中删除,所有其他节点移动,并且下一个迭代步骤跳过下一个节点(因为它的索引移动了)。

标签: javascript loops


【解决方案1】:

document.getElementsByClassName 返回一个HTMLCollection,它没有forEach 的定义。但是,您可以像这样使用Array.from() 将其转换为一个定义了一个的数组:

var collection = Array.from(document.getElementsByClassName("app-form-to-js"));
collection.forEach(function(node){...});

编辑:

正如@Preciel 向我指出的,NodeList 对象确实有一个类似于数组的forEach() 函数。如果您更愿意使用它,可以将document.getElementsByClassName("app-form-to-js") 替换为document.querySelectorAll(".app-form-to-js"),这将返回NodeList 而不是HTMLCollection

【讨论】:

  • document.getElementsByClassName("app-form-to-js").forEach(function(node) {}); 进行迭代...正如我所说,它在第一次迭代后停止,所以它至少迭代一次。正如我在第二个代码示例中所写的,一旦我稍微调整一下,循环就会起作用。它没有告诉我为什么从我更改或删除节点的那一刻起循环停止。还是仅仅因为它是HTMLCollection
  • 老实说,根据JavaScript documetnation,您发布的代码根本不应该工作。它可能只进行一次迭代,因为HTMLCollection 是一个对象,而 foreach 迭代了一组对象,但你的猜测和我的一样好。我提供的解决方案是最常见的方法。
  • 似乎完全支持我:developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach(除了IE,但谁在乎IE...)
  • HTMLCollectionNodeList 不同。
  • querySelectorAll() 给你一个NodeList 虽然如果你宁愿使用它而不是getElementsByClassName()
【解决方案2】:

另一种使用 ES6 扩展运算符创建数组的方法(这是我的首选方法):

const elements = [...document.getElementsByClassName("app-form-to-js")];
elements.forEach((node)=>{...});
//OR:
elements.map((node,i)=>{... return node});
//Etc...

如果你使用 .map() 方法,你可以直接对元素进行更改,它会反映在 DOM 等中 - 非常强大的技术(记得在函数中返回修改后的节点)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-15
    • 2015-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多