我在页面中有以下元素:
<div class="cl1 cl2"></div>
<div class="cl1 cl2"></div>
<div class="cl1 cl2"></div>
当我运行此代码时:
<script>
var elems = document.getElementsByClassName("cl1");
for (var i = 0; i < elems.length; i++) {
console.log(i + ": " + elems[i].className);
}
</script>
我可以看到:
0 cl1 cl2
1 cl1 cl2
2 cl1 cl2
在控制台中。
但是这段代码:
<script>
var elems = document.getElementsByClassName("cl1");
for (var i = 0; i < elems.length; i++) {
console.log(i + ": " + elems[i].className);
elems[i].className = 'cl3'; // or = '' (removing all classes)
}
</script>
给出:
0 cl1 cl2
1 cl1 cl2
第一次运行,并且:
0 cl1 cl2
第二次运行。
不修改所有元素的原因是什么?当我们触摸elems.length
时,我可以看到elems[i].className
正在减少,但是原因是什么?
如果我们添加var n = elems.length
并使用i < n
更改for循环,则会出现Cannot read property 'className' of undefined
错误。
问题是如何从第一次修改所有类?
因为我认为以下代码看起来非常愚蠢:
var elems = document.getElementsByClassName("cl1");
while (elems.length) {
for (var i = 0; i < elems.length; i++) {
console.log(i + ": " + elems[i].className);
elems[i].className = 'cl3';
}
elems = document.getElementsByClassName("cl1");
}
答案 0 :(得分:2)
问题是项目是一个实时NodeList,这意味着无论何时访问items.length,都会重新评估列表。 删除元素时,列表会变短,但保留索引。
您可以先将NodeList转换为数组
var items = [].slice.call(doc.getElementsByClassName('foo'));
删除DOM元素时,数组大小不会改变。
答案 1 :(得分:1)
getElementsByClassName
函数返回NodeList,而不是数组。 NodeList对象实时 - 它们在更改时跟踪DOM。 ( edit - 原来并非所有NodeList对象都是实时的,但是从该函数返回的对象是。)
当您更改第一个元素的类时,它将不再是元素列表的一部分。因此,当你增加“i”时,你会跳过一个。
您可以将NodeList对象转换为数组(请参阅@ ama2的答案),或者您不能更改“i”,即从所选集中删除元素。