很有意思的一个bug,起初看到同事对一段代码的批注:
批注地方的代码(也就是for里面的i),在实际触发时,返回是是7,而理想情况下我们希望点击哪个datagrid就返回哪个i,实际则是每次都是7,也就是for结束后的结果,6,i++,所以是7。
那么为什么会这样呢?
抱着好奇的心态我用一个简单的demo复现了该问题:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="./jquery-1.8.3.min.js"></script> </head> <body> <input type="button" value="按钮1" id="btn1"> <input type="button" value="按钮2" id="btn2"> <input type="button" value="按钮3" id="btn3"> </body> </html> <script> $(function () { for (var i = 1; i <= 3; i++) { $("#btn" +i).on("click",function(){ alert("触发点击事件!" + i); }) } }) </script>
研究一二之后知道了原因:
1、for是同步的,但事件是异步的,所以代码跑完了,这个时候注册事件,i就是最新的值了
2、var作用域是全局的,由于没有限制作用域,每次注册事件访问的都是同一个i
这里的注册事件我的理解分为两步,一步是声明事件,即我要注册这个dom的事件了,哪个呢,就是"#btn" +i ,另一个步则是实现事件逻辑,即我要怎么做了。
因此在声明的时候,代码是同步逻辑,可以取到当前的i,但是实现事件逻辑的时候,由于是异步的,for已经走完了才开始走事件的实现逻辑,同时由于使用的var进行定义变量,那么全局到处可读,这个时候i就是i++后的值了。
知道原因后解决起来就很简单,控制下i的作用域,var i 改成let i 就可以了,这是最简单最好用的写法,此时i已经是块级作用域,所以后续实现事件逻辑时,每个事件里的i就是各自的i了,i++不会再把其他事件里的i给累加。
大致上就是这么一个过程。很简单的一个问题,但是也涵盖了一些知识点在里面。虽然同事当时未能找到原因,不过通过其他方法也解决了这个问题,他在外层定义了一个变量gridID,每次切换tabs时更新这个gridID,这样代码就OK了。
方法有很多,知道是什么原因就好解决了。
参考博客:https://blog.csdn.net/qq_42539194/article/details/113920185
标签:逻辑,编程,作用域,代码,JavaScript,++,事件,var From: https://www.cnblogs.com/sunshine-wy/p/18583723