为什么"forEach.call"不通过类删除遍历每个节点?



我正在删除forEach.call中的类。由于某种原因,它只调用一次,如下所示。

var all_active = document.getElementsByClassName("active")
Array.prototype.forEach.call(all_active, function(el) {
  el.classList.remove("active");
  console.log(el.tagName);
});
<li class="active dropdown">
  <a>123</a>
  <div class="dropdown-content">
    <a class="active">1</a>
    <a>1</a>
    <a>1</a>
    <a>1</a>
    <a>1</a>
    <a>1</a>
  </div>
</li>

输出是LI,而我希望它能给出LI, A。为什么?

NodeList是元素的实时集合。从第一个元素中删除类时,集合的长度也会减小。因此,forEach()将得出结论,因为它已经处理了正确数量的元素。

ASCII 插图可能会有所帮助:

 # On first iteration:      # After first iteration:
┌───────────┬──────────┐   ┌──────────┬──────────┐   
│ NodeList  │ Iterator │   │ NodeList │ Iterator │
├───────────┼──────────┤   ├──────────┼──────────┤
│ li.active │   <──    │   │ a.active │          │
├───────────┼──────────┤   ├──────────┼──────────┤
│ a.active  │          │   │          │    <─    │
└───────────┴──────────┘   └──────────┴──────────┘

第一次迭代后,li不再在集合中,因为它不再与"active"类选择器匹配。


您可以通过使用 Array.from()NodeList转换为数组来回避该问题。修改节点时,数组内容不会更改,它仍将指向初始节点集。

var all_active = document.getElementsByClassName("active");
Array.from(all_active).forEach(function(el) {
  el.classList.remove("active");
  console.log(el.tagName);
});
<li class="active dropdown">
  <a>123</a>
  <div class="dropdown-content">
    <a class="active">1</a>
    <a>1</a>
    <a>1</a>
    <a>1</a>
    <a>1</a>
    <a>1</a>
  </div>
</li>

最新更新