【解决方案】闭包函数在for循环中的使用案例——for循环绑定监听事件索引值总是最后一个

时间:2022-10-06 21:16:06

请看以下两段代码,思考一下运行的结果是否一致呢?

代码一:

for (var i = 0; i < as.length; i++) {
(function () {
var j = i;
as[j].tt = tt;
as[j].onclick = function () {
this.tt.slide(j);
return false;
}
})();
}

代码二:

for (var i = 0; i < as.length; i++) {
// (function () {
// var j = i;
as[i].tt = tt;
as[i].onclick = function () {
this.tt.slide(i);
return false;
}
// })();
}

答案是不一致的,可以在循环内部绑定点击事件中输出索引值,如下:

代码一:

for (var i = 0; i < as.length; i++) {
(function () {
var j = i;
as[j].tt = tt;
as[j].onclick = function () {
console.log(j);
this.tt.slide(j);
return false;
}
})();
}

代码二:

for (var i = 0; i < as.length; i++) {
// (function () {
// var j = i;
as[i].tt = tt;
as[i].onclick = function () {
console.log(i);
this.tt.slide(i);
return false;
}
// })();
}

假设as.length = 3 ; 当用户触发点击事件,

代码一运行的结果:1或2或3 (绑定成功);

代码二运行的结果:控制台输出的值始终是 3 (绑定失败)。


原因分析:js引擎的解析机制是,执行的时候将for循环中代码执行,这个时候i变成最后的值,当发生onclick事件时,会找到运算之后的i,因此绑定的事件是最后的。


所以代码一采用了闭包函数的解决方法,成功的将循环的索引值传递到点击函数内部。


此处除了使用闭包的方法外,还可以通过给对象添加一个属性,通过属性来传递索引值,如下代码所示:

for (var i = 0; i < as.length; i++) {
as[i].tt = tt;
as[i].index = i;
as[i].onclick = function () {
console.log(i);
console.log(this.index);

this.tt.slide(this.index);
return false;
}
}

此时输出结果:3,0 或 3,1 或 3,2  绑定成功

总之 i 的值是不变的。。。


参考资料: for循环绑定监听事件索引值总是最后一个