[编程笔记] JavaScript作用域问题

    很有意思的一个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

posted @   顾星河  阅读(48)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
历史上的今天:
2020-12-03 C#异步编程

整理中...

点击右上角即可分享
微信分享提示