需求
我现在需要实现一个需求:为许多个li绑定上一个点击事件。
上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div class="a">
<ul class="b">
<li>我是li标签1</li>
<li>我是li标签2</li>
<li>我是li标签3</li>
<li>我是li标签4</li>
<li>我是li标签5</li>
</ul>
</div>
<script>
// 记得要用 querySelectorAll
var lis = document.querySelectorAll('.a .b li')
// console.log(lis[0])
// 现在我需要为每一个li都绑定上一个点击事件
for (var i = 0; i < lis.length; i++) {
// console.log(lis[i])
lis[i].onclick = function () {
console.log(`下标为${i}的li标签被点击了!`)
}
}
</script>
</body>
</html>
结果如下所示:不管点击哪一个li标签,都会显示下标为5的li标签被点击了!。
解释
首先,for循环是一个同步执行代码,而回调函数onclick是一个异步执行代码。同步函数与异步函数之间,同步函数是先执行的。也就是说,整个for循环都执行完毕了,当for循环中i的值自增到5的时候,for循环结束。i的值停留在了5。这就是上面执行结果出现的原因。
如何解决
1. 采用let
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div class="a">
<ul class="b">
<li>我是li标签1</li>
<li>我是li标签2</li>
<li>我是li标签3</li>
<li>我是li标签4</li>
<li>我是li标签5</li>
</ul>
</div>
<script>
// 记得要用 querySelectorAll
var lis = document.querySelectorAll('.a .b li')
// console.log(lis[0])
// 现在我需要为每一个li都绑定上一个点击事件
- for (var i = 0; i < lis.length; i++) {
+ for (let i = 0; i < lis.length; i++) {
// console.log(lis[i])
lis[i].onclick = function () {
console.log(`下标为${i}的li标签被点击了!`)
}
}
</script>
</body>
</html>
解释
let 具备块级作用域,循环几次,就相当于出现了几个全新的i,所以不存在var所存在的问题。
var只有函数作用域和全局作用域,简单来说,就是for循环管不住var定义的变量,会带来一系列的麻烦。如你已经很熟悉的变量提升
什么是变量提升?
变量提升就是在变量声明前是可以使用的,并且不会报错,但是它的值会是undefined
2. 自定义下标
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div class="a">
<ul class="b">
<li>我是li标签1</li>
<li>我是li标签2</li>
<li>我是li标签3</li>
<li>我是li标签4</li>
<li>我是li标签5</li>
</ul>
</div>
<script>
// 记得要用 querySelectorAll
var lis = document.querySelectorAll('.a .b li')
// console.log(lis[0])
// 现在我需要为每一个li都绑定上一个点击事件
for (var i = 0; i < lis.length; i++) {
// console.log(lis[i])
lis[i].index = i
lis[i].onclick = function () {
var idx = this.index
console.log(`下标为${idx}的li元素被点击了!`)
}
}
</script>
</body>
</html>
效果如下:
最后
平常各位小伙伴在工作中或者做项目的时候,遇到var和回调函数的时候,要多留个心眼了。