<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>珠峰在线Web高级课</title>
</head>
<body>
<!-- 在结构上设定自定义属性index,存储按钮的索引 -->
<button index='0'>我是第1个按钮</button>
<button index='1'>我是第2个按钮</button>
<button index='2'>我是第3个按钮</button>
</body>
</html>
1、这种方式肯定是不能实现的,因为i是全局的变量,循环结束之后,i变成了button.length 为3
<script>
var buttons = document.querySelectorAll('button'); //=>NodeList“类数组”集合
for (var i = 0;i < buttons.length;i++) {
buttons[i].onclick = function () {
console.log(`当前点击按钮的索引:${i}`);
};
}
</script>
2、方案一:基于“闭包”的机制完成 「每一轮循环都产生一个闭包,“存储对应的索引”;点击事件触发,执行对应的函数,让其上级上下文是闭包即可」
var buttons = document.querySelectorAll('button');
for (var i = 0; i < buttons.length; i++) {
// 每一轮循环都会形成一个闭包,存储私有变量i的值(当前循环传递的i的值)
// + 自执行函数执行,产生一个上下文EC(A) 私有形参变量i=0/1/2
// + EC(A)上下文中创建一个小函数,并且让全局buttons中的某一项占用创建的函数
(function (i) {
buttons[i].onclick = function () {
console.log(`当前点击按钮的索引:${i}`);
};
})(i);
}
3、方案二:跟方案一一样
var buttons = document.querySelectorAll('button');
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = (function (i) {
return function () {
console.log(`当前点击按钮的索引:${i}`);
};
})(i);
}
4、基于LET这种玩法也是“闭包”方案
let buttons = document.querySelectorAll('button');
for (let i = 0; i < buttons.length; i++) {
buttons[i].onclick = function () {
console.log(`当前点击按钮的索引:${i}`);
};
}
解析:浏览器在每一轮循环的时候,帮助我们形成的“闭包”
let buttons = document.querySelectorAll('button');
for (let i = 0; i < buttons.length; i++) {
// 父级“快级上下文”:控制循环
// 第一轮循环 私有的块级上下文EC(B1) i=0
// ->当前上下文中创建的一个小函数,被全局的按钮的CLICK占用了,EC(B1)不会被释放 “闭包”
buttons[i].onclick = function () {
console.log(`当前点击按钮的索引:${i}`);
};
}
------------------------以上三种解决方案都是闭包的原理----------------------
5、自定义属性 「性能强于闭包」
var buttons = document.querySelectorAll('button');
for (var i = 0; i < buttons.length; i++) {
// 每一轮循环都给当前按钮(对象)设置一个自定义属性:存储它的索引
buttons[i].myIndex = i;
buttons[i].onclick = function () {
// this -> 当前点击的按钮
console.log(`当前点击按钮的索引:${this.myIndex}`);
};
}
6、 事件委托 「比之前的性能提高40%-60%」
-
不论点击BODY中的谁,都会触发BODY的点击事件
-
ev.target是事件源:具体点击的是谁
document.body.onclick = function (ev) { var target = ev.target, targetTag = target.tagName; // 点击的是BUTTON按钮 if (targetTag === "BUTTON") { var index = target.getAttribute('index'); console.log(`当前点击按钮的索引:${index}`); } };