1

我在页面中有以下元素:

<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并更改 for 循环,i < n我们将得到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");
}
4

2 回答 2

2

问题是 items 是一个活动的 NodeList,这意味着每当您访问 items.length 时,都会重新评估该列表。当您删除元素时,列表会变短,但您会保留索引。

您可以先将 NodeList 转换为数组

    var items = [].slice.call(doc.getElementsByClassName('foo'));

删除 DOM 元素时,数组大小不会改变。

于 2012-07-28T22:34:05.200 回答
1

getElementsByClassName函数返回一个 NodeList,而不是一个数组。NodeList 对象是实时的——它们跟踪 DOM 的变化。(编辑——事实证明,并非所有 NodeList 对象都是活动的,但从该函数返回的对象却是活动的。)

当您更改第一个元素的类时,它不再是元素列表的一部分。因此,当您增加“i”时,您会跳过一个。

您可以将 NodeList 对象转换为数组(请参阅@ama2 的答案),或者您不能更改“i”,因为您正在从选定的集合中删除元素。

于 2012-07-28T22:33:30.367 回答