如果我使用
var temp = document.querySelectorAll(".class");
for (var i=0, max=temp.length; i<max; i++) {
temp[i].className = "new_class";
}
一切正常。所有节点都会更改其类。
但是,有了gEBCN:
var temp = document.getElementsByClassName("class");
for (var i=0, max=temp.length; i<max; i++) {
temp[i].className = "new_class";
}
我收到错误。代码在某个时刻跳出循环,而不是使用msg“无法将className设置为null”完成作业 我知道这是静态vs live nodelist问题(我认为),但是因为gEBCN要快得多,我需要遍历庞大的节点列表(树),我真的想使用getElementsByClassName。 有什么办法可以坚持使用gEBCN而不是被迫使用querySelectorAll吗?
答案 0 :(得分:16)
这是因为HTMLCollection
返回的getElementsByClassName
是有效的。
这意味着如果您将"class"
添加到某个元素的classList中,它会神奇地出现在temp
中。
对位也是如此:如果删除"class"
内的元素的temp
类,它将不再存在。
因此,更改类会重新索引集合并更改其长度。所以问题是你预先迭代它的长度,而不考虑索引的变化。
要避免此问题,您可以:
使用非实时收藏。例如,
var temp = document.querySelectorAll(".class");
将实时HTMLCollection
转换为数组。例如,使用其中一个
temp = [].slice.call(temp);
temp = Array.from(temp); // EcmaScript 6
向后迭代。例如,请参阅@Quentin's answer。
考虑指数的变化。例如,
for (var i=0; i<temp.length; ++i) {
temp[i].className = "new_class";
--i; // Subtract 1 each time you remove an element from the collection
}
while(temp.length) {
temp[0].className = "new_class";
}
答案 1 :(得分:9)
在列表后面循环,然后元素将从最后消失(你不再在那里寻找)。
for (var i = temp.length - 1; i >= 0; i--) {
temp[i].className = "new_class";
}
但请注意,IE 8支持querySelectorAll但不支持getElementsByClassName,因此您可能希望更喜欢querySelectorAll以获得更好的浏览器支持。
或者,不要删除现有的课程:
for (var i=0, max=temp.length; i<max; i++) {
temp[i].className += " new_class";
}