HTMLCollection 添加不同的属性对实时集合的影响不同,需要解释

HTMLCollection adding different attributes affects the live collection differently, need explanation

所以我们都知道 document.getElementsByClassNamedocument.getElementsByTagName 是实时 HTML 集合。

我用谷歌搜索,似乎找不到这个问题的答案,也许我只是不明白,谁能给我解释一下?

所以我做了 2 个示例,一个添加了 class 属性,另一个添加了 bgcolor。为什么第一个按预期行事,而另一个却完成了工作...

为什么 TagName 的工作方式不同,即使它是第一个示例中的 HTMLCollection?

我怎么知道哪个可以正常工作,哪个不能正常工作?

https://jsfiddle.net/adkuca/84ryjp7s/2/

https://jsfiddle.net/adkuca/f1o9h7be/

var ran = document.getElementsByClassName('wasd');
/*var ran = document.getElementsByTagName('td');*/

document.getElementById('btn').addEventListener('click', func);
function func() {
  console.log(ran); //HTMLCollection, all 6
    console.log(ran.length); //6 with both
    for (let i = 0; i < ran.length; i++) {
        ran[i].setAttribute("class", "green");
    }
    console.log(ran); //HTMLCollection, all 6 with TagName, every 2nd with ClassName
    console.log(ran.length); //6 with TagName, 3 with ClassName
}
tr, td {
    border: 1px solid black;
    height: 20px;
    width: 20px;
}

.green {
  background-color: green;
}
<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
    <button id="btn">func</button>
    <table>
        <tr>
            <td class="wasd"></td>
            <td class="wasd"></td>
            <td class="wasd"></td>
        </tr>
        <tr>
            <td class="wasd"></td>
            <td class="wasd"></td>
            <td class="wasd"></td>
        </tr>
    </table>
    </body>
</html>

var ran = document.getElementsByClassName('wasd');
/*var ran = document.getElementsByTagName('td');*/

document.getElementById('btn').addEventListener('click', func);
function func() {
  console.log(ran); //HTMLCollection, all 6
    console.log(ran.length); //6 with both
    for (let i = 0; i < ran.length; i++) {
        ran[i].setAttribute("bgcolor", "green");
    }
    console.log(ran); //HTMLCollection, all 6
    console.log(ran.length); //6 with both
}
tr, td {
    border: 1px solid black;
    height: 20px;
    width: 20px;
}
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
    <button id="btn">func</button>
    <table>
        <tr>
            <td class="wasd"></td>
            <td class="wasd"></td>
            <td class="wasd"></td>
        </tr>
        <tr>
            <td class="wasd"></td>
            <td class="wasd"></td>
            <td class="wasd"></td>
        </tr>
    </table>
    </body>
</html>

它们都以相同的方式正常工作。 className 的工作方式似乎有所不同,因为您在处理它时有效地从正在使用的列表中删除了元素。

当您使用 setAttribute("class", "green"); 时,您将 "wasd" class 替换为 "green"

如果您添加 class 而不是使用 ele.classList.add(class)

替换当前的,这将起作用

https://jsfiddle.net/84ryjp7s/3/

好吧,给可能有同样问题的人总结一下。

所以如果你得到一个带有 ClassName 的集合,意味着一切都会正常运行,直到你删除当前的 class 你用来收集集合。

如果它是 class="a b",您可以添加任何 class,但如果您 delete/change 其中 1 个它会破坏 HTML 集合

与任何其他相同HTML集合/实时节点列表

如果你用 getElementsByTagName 收集,你可以改变 class 但你不能改变 td,如果你试图删除 div,你毁了收集

https://jsfiddle.net/adkuca/c00fqmts/

因为它计算你正在删除 td,因此改变 HTML 集合,将其缩小 1,因此将 ran.length 缩小 1,所以你得到一半迭代,然后添加一个新的 td 少了一半。

检查这个:https://jsfiddle.net/adkuca/c7jb0es8/

但如果你真的想收集 classes 和 classname 然后更改它们,你可以将它们存储到一个数组中然后更改。

    Array.from(document.getElementsByClassName('wasd')).forEach(function(itm){
    itm.setAttribute('replaced-wasd');
});

var ran = document.getElementsByClassName('wasd');
/*var ran = document.getElementsByTagName('td');*/

document.getElementById('btn').addEventListener('click', func);
function func() {
  console.log(ran); //HTMLCollection, all 6
    console.log(ran.length); //6 with both
    for (let i = 0; i < ran.length; i++) {
      console.log(ran.length);
        ran[i].setAttribute("class", "green");
        console.log(ran.length);
        console.log("i = " + i);
        console.log(ran);
    }
    console.log(ran); //HTMLCollection, all 6 with TagName, every 2nd with ClassName
    console.log(ran.length); //6 with TagName, 3 with ClassName
}
tr, td {
    border: 1px solid black;
    height: 20px;
    width: 20px;
}

.green {
  background-color: green;
}
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
    <button id="btn">func</button>
    <table>
        <tr>
            <td class="wasd"></td>
            <td class="wasd"></td>
            <td class="wasd"></td>
            <td class="wasd"></td>
            <td class="wasd"></td>
            <td class="wasd"></td>
        </tr>
        <tr>
            <td class="wasd"></td>
            <td class="wasd"></td>
            <td class="wasd"></td>
            <td class="wasd"></td>
            <td class="wasd"></td>
            <td class="wasd"></td>
        </tr>
    </table>
    </body>
</html>