2013-03-22 97 views
13

首先,对不起我的英语不好......getElementsByClassName方法 - 奇怪的行为

我写了一个函数来改变类元素来改变其性质。 出于某种原因,只有一些元素发生了变化,我花了几个小时才找到解决方案,但他对我来说似乎很古怪,也许你可以向我解释。

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

不工作为好,Demo here,[对铬25和FF],所以我把循环系数:

function replace(){ 
    var elements = document.getElementsByClassName('classOne'); 
    for (var i=0; i<elements.length;i) { //----here the different --- i without ++ 
    elements[i].className = 'classTwo';    
    } 
} 

这非常适用!似乎被称为“推”,并没有系数需要... 这是正常的?这与我见过的例子不同。

在此先感谢!

回答

18

发生了什么是一个奇怪的副作用。当您为elements的每个元素重新分配className时,该元素将从数组中移除! (其实,正如@ user2428118指出的那样,elements是一个类似于数组的对象,而不是数组,请参阅this thread)。这是因为它不再具有classOne类名。当你的循环退出时(在第二种情况下),elements数组将为空。通过增加i,你跳过有classOne类(原)元素的一半

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

在你的第一种情况下,:

你可以写你的环路。顺便说一下,这是一个很好的问题。经过充分研究和明确。

+1

给予好评的答案和解释 – 2013-03-22 04:08:40

+0

谢谢!听起来没错.. 但是...它是有意义的编程? “元素”是一个存在的对象,而不是动态的对象,没有你可以改变? – MeNa 2013-03-22 04:38:12

+0

@MeNa - 尽管'elements'变量对你的函数是局部的,它所引用的数组也可以被DOM访问(并由其维护)。每个元素的'className'属性实际上触发了DOM机制中的setter函数。该函数的一个副作用是从元素引用的数组中移除该元素。所以它不会改变“没有你”;它会因为您更改其某个元素的'className'属性而发生更改。引用旧的圣贤:_“这不是一个错误,这是一个功能!”_ – 2013-03-22 04:47:04

4

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

+0

Tnx。事实上,'现场收藏'这个词很好地解释了这一点。 – MeNa 2013-03-22 10:49:55

+1

并非所有NodeList集合都是实时的。某些“获取”方法(如querySelectorAll())会返回不受后续DOM更改影响的STATIC NodeList。 – SHH 2014-12-27 05:25:21

-2

或恢复循环,通过长度为1开始,下台0

+0

你看过接受的答案吗? – 2014-12-01 14:57:15

+0

是的,那也可以,但这个问题需要解释而不是解决方案。下一次为 – Bergi 2014-12-01 15:02:42

+0

,http:// stackoverflow。com/help /如何回答:)享受! – 2014-12-01 15:08:32