为什么类“大”只添加到数组的最后一个元素?

时间:2021-02-12 19:04:07

标签: javascript html

我有一个如下所示的网站。 当一个文本被点击时,被点击的文本将得到一个名为 large 的类,并且文本大小将变为 25pt。要了解我如何分配事件和类 large,请查看 js 代码。我遇到的问题是,当单击“我喜欢游泳”文本时,大班级会添加到文本“我喜欢篮球”中。为什么会这样?谁能帮我解决这个问题?

const arraySportsText = Array.from(document.getElementsByClassName('sportsText'));
for (index in arraySportsText) {
  arraySportsText[index].addEventListener("click", () => arraySportsText[index].classList.add('large'))
}
body {
  font-size: 15pt;
}

.large {
  font-size: 25pt;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="styles/style.css">
</head>

<body>
  <h1>Sports</h1>


  <p class="sportsText">I like swimming</p>

  <p class="sportsText">I like basketball</p>

  <script src="scripts/hobby.js"></script>
</body>

</html>

1 个答案:

答案 0 :(得分:2)

您的循环变量未显式声明,因此它获得了一个隐式 var 声明作为全局变量。

您在事件处理程序中使用循环变量会在 index 周围创建 a closure,因此当这些处理程序运行(稍后)时,它们访问该循环变量的最后一个值,因此仅访问最后一个元素受到影响。

使用 let 声明具有块作用域的循环变量来解决问题。

  • 另外,don't use .getElementsByClassName() 和 使用 .querySelectorAll()
  • 而且,.getElementsByClassName().querySelectorAll() 返回类似于数组的集合,因此它们中的任何一个都不是 需要 Array.from() 如果您要使用计数循环来 迭代它。
  • 而且,for/in 循环不应用于枚举数组 Array 的所有属性,而不仅仅是索引。 for/in should only be used on objects
  • 最后,.querySelectorAll() 返回的集合可以是 用 Array.prototype.forEach() 方法循环,​​删除 需要计数循环。

所以,重新编写的代码应该是:

// Looping over the collection returned from .querySelectorAll()
// eliminates the need for a counting loop, which also removes
// the need to use that index in the event handler, which in turn,
// eliminates the closure problem you had in the first place.
document.querySelectorAll('.sportsText').forEach(function(element){
  element.addEventListener("click", () => element.classList.add('large'))
});
body   { font-size: 15pt; }
.large { font-size: 25pt; }
<h1>Sports</h1>
<p class="sportsText">I like swimming</p>
<p class="sportsText">I like basketball</p>