Javascript 从GetElementsByCassName迭代HTMLCollection时的奇怪行为

Javascript 从GetElementsByCassName迭代HTMLCollection时的奇怪行为,javascript,html,getelementsbyclassname,htmlcollection,Javascript,Html,Getelementsbyclassname,Htmlcollection,我编写了一个函数来更改元素类以更改其属性。出于某种原因,只有一些元素发生了变化。我花了几个小时才找到解决办法,但我觉得很奇怪。也许你能给我解释一下 这不起作用: function replace(){ var elements = document.getElementsByClassName('classOne'); for (var i = 0; i < elements.length; i++) { elements[i].className = 'classTwo

我编写了一个函数来更改元素类以更改其属性。出于某种原因,只有一些元素发生了变化。我花了几个小时才找到解决办法,但我觉得很奇怪。也许你能给我解释一下

这不起作用:

function replace(){
  var elements = document.getElementsByClassName('classOne');

  for (var i = 0; i < elements.length; i++) {
    elements[i].className = 'classTwo';               
  }
}

这很有效!似乎调用了
push
,不需要增量。这正常吗?这与我看到的例子不同。

发生的是一个奇怪的副作用。当您为
元素
的每个元素重新分配
类名
时,该元素将从数组中删除!(事实上,正如@user2428118所指出的,
elements
是一个类似数组的对象,而不是数组。请参阅以了解区别。)这是因为它不再具有
classOne
类名。当循环退出时(在第二种情况下),
元素
数组将为空

您可以将循环编写为:

while (elements.length) {
    elements[0].className = 'classTwo'; // removes elements[0] from elements!
}
在第一种情况下,通过增加
i
,您将跳过具有class
classOne
的一半(原始)元素


顺便提一下,这个问题问得很好。经过充分研究和明确。

getElementsByClassName
返回节点列表。节点列表集合是活动集合,这意味着文档的修改会影响集合

或将循环还原,从长度-1开始,然后下降到0

谢谢!听起来不错。。但是这是理性编程吗?“elements”是一个exist对象,而不是可以在没有您的情况下动态更改的对象?@MeNa-虽然
elements
变量是函数的局部变量,但它引用的数组也可以由DOM访问(并由DOM维护)。每个元素的
className
属性实际上触发DOM机器中的setter函数。该函数的一个副作用是从
elements
引用的数组中删除元素。所以它不会改变“没有你”;它的更改是因为您更改了它的一个元素的
className
属性。引用古代圣人的话:“这不是一个bug;这是一个特性!”@TedHopp-再次感谢你!现在一切都清楚了。(顺便说一句,感谢“while()”,这是一个很好且优雅的解决方案。)您可能应该提到,元素实际上不是一个数组,而只是一个类似datastructureTnx的数组。事实上,“实时收集”一词很好地解释了这一点。并非所有节点列表收集都是实时的。一些“fetch”方法,如querySelectorAll(),返回静态节点列表,该列表不受后续DOM更改的影响。是的,这也可以,但问题需要解释而不是解决方案。我从未听说过这个术语。JavaScript为循环调用
的最后一部分(或在规范的某些上下文中)和
i++
an(或规范中的广义)。
while (elements.length) {
    elements[0].className = 'classTwo'; // removes elements[0] from elements!
}