在做一个tab菜单点击切换的过程中遇到一个问题,就是每次点击之后都会将最后的一个区块显示出来, 检查之后得到的结果就是每次点击菜单之后得到的值都是最大值。于是问题就出来了,原因在于javascript事件处理器在线程空闲时间不会运行,导致每次执行后的结果为 array.length 的最大值。

—— 方法不一定适应每个人每台机器,如不能成功,请问度娘。

1. 问题代码展示

html代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="box">
<button class="button">1</button>
<button class="button">2</button>
<button class="button">3</button>
<button class="button">4</button>
<button class="button">5</button>
</div>
</body>
</html>

js 每次输出最大值的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
window.onload = function () {
var oButton = document.querySelectorAll('.button');
for (var i = 0; i < oButton.length; i++) {
oButton[i].onclick = function() {
console.log(i);
}
}
}
// 4
// 4
// 4
// 4
// 4

以上代码都是正常思维下的想法,但是事实是每次都输出了oButton.length的最大个数值。

2. 正确的解决方案

1. 方法一

加一层闭包,返回一个函数作为响应事件

1
2
3
4
5
6
7
8
for (var i = 0; i < oButton.length; i++) {
oButton[i].onclick = function(a) {
//返回一个函数
return function() {
console.log(a);
}
}(i);
}

2. 方法二

加一层闭包,i 以局部变量形式传递给内存函数

1
2
3
4
5
6
7
8
9
for (var i = 0; i < oButton.length; i++) {
(function () {
//调用时局部变量
var temp = i;
oButton[i].onclick = function() {
alert(temp);
}
})();
}

3. 方法三

添加自定义属性的方法,通过js把i的值保存在html 的index属性上在访问。

1
2
3
4
5
6
for (var i = 0; i < oButton.length; i++) {
oButton[i].index = i;
oButton[i].onclick = function() {
alert(this.index);
}
}