javascript - 为什么闭包可以解决js中循环绑定事件的问题?

 幸福的xinwangnanfei_736 发布于 2022-11-10 12:30

今天遇到了利用循环给元素绑定事件的问题,相信大家应该都遇到过这个问题。

我的代码

var hint = ["必填,长度为4-18个字符", "", "再次输入相同密码", "格式: example@github.com", ""];
    var inputIDs = ["ip-name", "ip-pwd", "ip-pwd-cfm", "ip-email", "ip-phone"];
    for (var i = 0; i

下面这段代码用闭包来解决的,但是我没看懂,为什么这样调用不会调用到循环结束时i的值了呢?
没有理解这里闭包的用法,有哪位可以解释一下吗?

for (var i = 0; i < 5; i++) { 
    var a = function(v){
        return function(){
            console.log(v)
        }
    }
    document.body.addEventListener('click',a(i))
}
8 个回答
  • i是全局变量,focus含有异步函数,当异步被调用时,i已经被修改了。
    只需要让i复制给一个局部变量即可

    2022-11-12 01:54 回答
  • click是一个异步操作,在事件执行的时候,i的值已经是5

    2022-11-12 01:54 回答
  • 改成下面就好了

    var hint = ["必填,长度为4-18个字符", "", "再次输入相同密码", "格式: example@github.com", ""];
        var inputIDs = ["ip-name", "ip-pwd", "ip-pwd-cfm", "ip-email", "ip-phone"];
        for (var i = 0; i<hint.length; i++) {
            document.getElementById(inputIDs[i]).addEventListener("focus", (function (i) {
                return function(e){
                    var tar = e.target.parentElement.getElementsByClassName("alert")[0];
                    tar.innerHTML = hint[i];
                };
            })(i));
        }
    2022-11-12 01:54 回答
  • 作用域问题,看看这篇文章

    2022-11-12 01:54 回答
  • 当循环结束以后i的值为length,所以每次都取不到值

    2022-11-12 01:54 回答
  • 需要知悉作用域链的知识并且理解闭包的概念。
    先看你的代码:
    var tar = e.target.parentElement.getElementsByClassName("alert")[0];tar.innerHTML = hint[i];这段代码是focus事件处理函数,只有在出发focus事件时才会执行。循环结束后,绑定了hint.length个事件处理函数,当这些处理函数执行时,他们都访问的是i变量,注意是同一个i变量,所以结果都一样。
    再来看看闭包:
    利用闭包的特点,当i传入时,闭包函数能够访问参数v,此时v保存的是i的值,也就是说闭包函数存储了这个i值,在需要的时候可以进行访问。

    我对闭包函数的理解就是给return的那个匿名函数开辟一片私有的空间,可以存放一些私有的变量或者函数。为什么不能在函数内部直接声明一些变量呢?因为函数内部的变量只有在函数执行期间才存在,那么变量上的值是变化的,而闭包函数的这篇私有空间会一直存在,这也是为什么说它会消耗内存的原因。

    2022-11-12 01:54 回答
  • 你的代码里,focus的回调函数再循环结束前并不会执行,等到回调执行的时候,i已经是hint.length了.
    闭包的方法,每次循环都会执行a(i),把当前的值传到a中,从而保存了这一轮i的值。

    2022-11-12 01:54 回答
  • 如果你不使用闭包,你引用的i就是全局作用域(看你的代码没有在一个函数里)里的i。document.getElementById(inputIDs[i])这里的i就是你绑定时候的i,但是当你调用绑定的事件的时候函数体里的i就不再是绑定时候的i而是循环执行完以后的i的值了,其实你能访问到循环执行完了的i的值也有点类似于闭包,函数执行完了,你还能访问还是里声明的变量。
    但是你使用了闭包就不一样了,document.body.addEventListener('click',a(i))这里把i以参数的形式传入a函数,这时候已经和循环里的i不一样了,他们指向了不同的地址只是值一样,如果这里你传入的参数是个对象类型,闭包函数里的参数就是你这个对象的引用的copy,你在循环下面修改了传入对象的属性,闭包函数里也会相应修改,但是修改对象的引用的话,闭包里则不会改变。

    2022-11-12 01:54 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有