无法遍历 document.getElementsByClassName()

Unable to iterate over document.getElementsByClassName()

提问人:Harsh Kasodariya 提问时间:7/8/2023 更新时间:7/8/2023 访问量:47

问:

我正在尝试遍历 返回的对象。返回的对象包含三个具有指定类名的元素。但是,当我尝试使用循环访问每个元素时,对象的行为就好像它是空的一样。document.getElementsByClassName()for0

以下是我在尝试调试时所做的控制台日志。

首先,我记录了返回的对象。

elements = document.getElementsByClassName("brute-force-effect");
console.log(elements);

输出

> HTMLCollection []
  > 0: div.tile.brute-force-effect.harsh
  > 1: div.tile.brute-force-effect.kaso
  > 2: div.name.brute-force-effect
> length: 3
> [[Prototype]]: HTMLCollection

显然,它包含了所有三个要素。但是,当我记录它的长度时

console.log(elements.length);

输出

0

我尝试按如下方式迭代它

for (e of elements) {
    console.log(e);
}

输出

No output

并且由于返回 ,以下方法,如类似stackoverflow问题的解决方案中提供的那样,也不起作用。elements.length0

for (i = 0; i < elements.length; i++) {
    console.log(elements.item(i));
}

输出

No output
JavaScript 循环 迭代器 getElementsByClassName

评论

1赞 Nick Parsons 7/8/2023
请注意,在输出中,集合的内容为 空,只有扩展版本才会显示元素。这是因为扩展版本在控制台中扩展集合时会显示集合的内容(因为一旦 DOM 加载,它就会被填充,因为 HTMLCollections 是“实时”的)。显示的日志本身实际上是记录时的内容。有关日志输出的详细信息,请参阅以下内容:Chrome 的 JavaScript 控制台在评估对象时是否懒惰?[]HTMLCollection [][]
0赞 Harsh Kasodariya 7/9/2023
@NickParsons我认为这消除了我所有的疑虑,谢谢。

答:

1赞 kevP-Sirius 7/8/2023 #1

您是否在以下范围内执行代码?

document.addEventListener("DOMContentLoaded", function() {
    // Your code here
});

评论

0赞 Harsh Kasodariya 7/8/2023
它奏效了,但我不明白这种行为,你能解释一下为什么会奏效吗?
0赞 kevP-Sirius 7/8/2023
嗯,通常是因为你的html代码是动态添加的,你需要等待你的页面完全加载,然后才能在你的DOM上正确执行操作,但是你的代码可以工作,这取决于客户端加载DOM的速度,但为了保证它的安全,我们在完全加载后执行所有操作。
0赞 Harsh Kasodariya 7/8/2023
是的,我得到了那部分,但仍然可以从一开始就访问所有元素,我将其存储在变量中。为什么迭代它不起作用?HTML 的动态特性是否会在我迭代变量之前更新它?document.getElementsByClassName
0赞 kevP-Sirius 7/8/2023
你明白了,document.getElementsByClassName 是在注入 html 的元素之前执行的。举个例子,如果你把你的代码放在一个settimeout函数中,等待几秒钟,你会看到它也可以工作,因为DOM将被完全加载
0赞 kevP-Sirius 7/8/2023
“HTML 的动态特性在我迭代之前会更新变量吗?”在初始化您的页面时,客户端为空。您的 javascript 和 html 在 DOMcontentloaded 事件的范围之外不是 100% 同步的。所以它更像是你的 javascript 运行一次,你的变量元素在执行后没有更新,所以它保持一个空数组。
0赞 Abdelrahman Khallaf 7/8/2023 #2

我认为您无法遍历返回的对象的原因是因为它是 HTMLCollection,而不是 Array。HTMLCollection 是一个活动对象,这意味着它会随着 DOM 的变化而变化。当您尝试循环访问 HTMLCollection 时,这可能是一个问题,因为在循环访问集合时,集合的长度可能会发生变化。document.getElementsByClassName()

要解决此问题,您需要将 HTMLCollection 转换为 Array。您可以使用该方法执行此操作。以下代码将执行此操作:Array.from()

const elements = document.getElementsByClassName("x");
const elementsArray = Array.from(elements);

for (const element of elementsArray) {
  console.log(element);
  element.innerHTML = "new text";
}
<html>
  <body>
    <div class="x">1</div>
    <div class="x">2</div>
    <div class="x">3</div>
    <div class="x">4</div>
    <script src="index.js"></script>
  </body>
</html>

评论

0赞 Harsh Kasodariya 7/8/2023
谢谢你的回答,但我认为 HTMLCollections 也是可迭代的。另一个解决方案对我有用。感谢您的帮助。