【问题标题】:Strange behavior when iterating over HTMLCollection from getElementsByClassName从 getElementsByClassName 迭代 HTMLCollection 时的奇怪行为
【发布时间】:2013-03-11 20:17:56
【问题描述】:

我写了一个函数来改变元素的类来改变它们的属性。由于某种原因,只有部分元素发生了变化。我花了几个小时才找到解决方案,但这对我来说似乎很奇怪。或许你可以给我解释一下。

这不起作用:

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

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

See the JSFiddle:只有第二个项目受到影响;只有每隔一个红色元素才会将颜色变为蓝色。

所以我将for 循环的最终表达式更改为不再增加i

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

  for (var i = 0; i < elements.length; i) { // Here’s the difference
    elements[i].className = 'classTwo';               
  }
}

这很好用!似乎push 被调用并且不需要增量。这是正常的吗?和我见过的例子不一样。

【问题讨论】:

标签: javascript html getelementsbyclassname htmlcollection


【解决方案1】:

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

你可以把你的循环写成:

while (elements.length) {
    elements[0].className = 'classTwo'; // removes elements[0] from elements!
}

在第一种情况下,通过递增 i,您将跳过一半具有 classOne 类的(原始)元素。

顺便说一句,问题很好。深入研究且清晰。

【讨论】:

  • 谢谢!听起来不错……但是……这是有意义的编程吗? “元素”是一个存在的对象,而不是没有你就可以改变的动态对象?
  • @MeNa - 虽然elements 变量是您的函数的本地变量,但它引用的数组也可由 DOM 访问(并由其维护)。每个元素的className 属性实际上触发了DOM 机制中的一个setter 函数。该函数的副作用之一是从elements 引用的数组中删除元素。所以它不会改变“没有你”;它发生了变化,因为您更改了其中一个元素的 className 属性。引用古人的话:“这不是错误;这是一个特性!”
  • @TedHopp - 再次感谢您!现在一切都清楚了。 (PS,感谢'while()',这是一个很好的优雅的解决方案。)
  • 您可能应该提到元素不是实际上一个数组,而仅仅是一个类似数组的数据结构
【解决方案2】:

getElementsByClassName 返回一个节点列表。 NodeList 集合是实时集合,这意味着文档的修改会影响集合。 more

【讨论】:

  • Tnx。事实上,“实时收藏”一词很好地解释了这一点。
  • 并非所有 NodeList 集合都是实时的。一些“获取”方法,例如 querySelectorAll(),返回不受后续 DOM 更改影响的 STATIC NodeList。
  • 它返回一个实时的HTMLCollection
【解决方案3】:

或者恢复循环,从length-1开始,逐步下降到0

【讨论】:

  • 是的,这也可以,但问题需要解释而不是解决方案。
猜你喜欢
  • 1970-01-01
  • 2016-04-22
  • 1970-01-01
  • 1970-01-01
  • 2013-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多