我正在删除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>