【事件循环机制】解决for循环异步事件只响应最后一个事件

打脸了,这并不是闭包的问题,而是一个事件循环机制

以下为错误解释
这是一个关于变量闭包的问题,以前做项目时遇到,那时候并没有想明白,换了另一种方法实现,今天看闭包的知识点时恍然大悟,于是,写出来记录下。

首先,主要涉及两个概念
变量的作用域:也就是变量的有效范围,函数内部变量的作用域也就只能在函数内部使用。
变量的生存周期:对于函数的局部变量,函数退出后也就失去了价值,他们也会随着函数调用的结束而销毁。

然后,上闭包应用。
假设页面上有5个div节点,我们通过循环来给每个div绑定onclick事件,按照索引顺序,点击第1个div时弹出0,点击第2个div时弹出1,以此类推。如果用常规的绑定就会出现题目中的问题。
原因:div节点的onclick事件是被异步触发的,当事件被触发的时候,for循环早已结束,此时变量i的值已经是5,所以在div的onclick事件函数中顺着作用域链从内到外查找变量i时,查找到的值总是5(注释部分代码可以尝试一下)。
解决办法:在闭包的帮助下,把每次循环的i值都封闭起来。当在事件函数中顺着作用域链中从内到外查找变量i时,会先找到被封闭在闭包环境中的i,如果有5个div,这里的i就分别是0,1,2,3,4:

最后,上代码,结合以上解释。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>闭包</title>
    </head>
    <style type="text/css">
        div {
            width: 100%;
            height: 50px;
            margin: 20px 0;
            border: aqua 1px solid;
            background: #00FFFF;
            cursor: pointer;
            
            display: flex;
            align-items: center;
            justify-content: center;
        }
        div:hover {
            background: chartreuse;
        }
    </style>
    <body>
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
        <div>5</div>
    </body>
    <script type="text/javascript">
        var nodes = document.getElementsByTagName('div');
        /* 未使用闭包前 */
//      for(var i=0,len=nodes.length; i<len; i++) {
//          nodes[i].onclick = function() {
//              alert(i);
//          }
//      }
        for(var i=0,len=nodes.length; i<len; i++) {
            (function(i){
                nodes[i].onclick = function() {
                    alert(i);
                }
            })(i)
            
        }
    </script>
</html>

效果截图:


image.png

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容