JavaScript与jQuery循环绑定点击事件异常问题咨询
为什么循环绑定点击事件会总是alert(12)?
嘿,这个问题我刚接触JS和jQuery的时候也踩过一模一样的坑!太经典的闭包作用域陷阱了,我来给你掰扯清楚:
先看循环绑定的问题根源
你写的循环代码里,i是用var声明的(或者没声明,默认挂到全局),它的作用域是整个循环所在的外层作用域,而不是每次循环的迭代块里。你给每个元素绑定的点击事件函数,并没有保存当时i的具体值,而是引用了同一个i变量。
等循环跑完的时候,i已经自增到12了——这时候不管你点击哪个c0到c11的元素,触发点击函数时,它会去当前作用域找i的值,自然就是12了。
再看逐个绑定为什么正常
而你逐个写的$("#c0").on("click", function(){alert(0)})这种代码,每个点击函数里的alert(0)、alert(1)都是直接使用了字面量数值。每个函数都“捕获”了自己对应的固定数字,和外部的变量没有关联,所以点击的时候就会弹出对应的正确数值。
给你几个可行的解决方案
- 用
let声明循环变量(ES6+推荐写法)let会在每次循环迭代时创建一个块级作用域的i,每个点击函数都会绑定当前迭代的那个独立的i值:
for (let i = 0; i < 12; i++) { $("#c" + i).on("click", function () { alert(i) }); }
- 用立即执行函数(IIFE)创建独立作用域
这是ES6之前常用的解决办法,把当前的i作为参数传给IIFE,让每个点击函数绑定的是IIFE里的局部变量:
for (var i = 0; i < 12; i++) { (function(num) { $("#c" + num).on("click", function () { alert(num) }); })(i); }
- 用jQuery的
each方法
jQuery的each回调会自带索引参数,每个回调函数都有自己的作用域,完美避开这个问题:
$.each($("[id^='c']"), function(index) { $(this).on("click", function() { alert(index); }); });
内容的提问来源于stack exchange,提问作者Sebastian Z.
相关产品推荐
相关产品推荐

