网站导航:首页-WEB前端/后端-循环添加异步事件中的循环变量

循环添加异步事件中的循环变量

最近更新:2019-12-28

在JavaScript中for循环语句非常常用,但如果想通过for循环添加异步代码时,在异步代码中有可能会有无法正常拿到循环变量的情况,我们用下面的一个例子来说明:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>循环添加异步事件中的循环变量</title>
</head>
<body>
    <button>按钮0</button>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <script>
        var aBtn = document.getElementsByTagName('button');
        for(var i = 0; i < aBtn.length; i++) {
            aBtn[i].onclick = function() {
                alert(i);
            };
        }
    </script>
</body>
</html>

当运行这段代码时,我们预想的是希望点击对应按钮,显示对应按钮的序号。但实际情况是点击任意一个按钮,都会弹框5,这种现象的原因是给按钮添加的点击事件属于异步代码,在添加点击事件时,其中的代码不会执行,等到点击按钮执行代码时,循环变量i早已循环完成值到5了.所以点击每个按钮都会弹窗5

了解了原因,就可以思考如何解决这个问题了,共有两种解决方案,一种是利用一个自定义属性,另一种是利用闭包。下面对这三种情况分别举例:

利用自定义属性

通过添加一个自定义变量存住循环变量的值,后续直接调用自定义属性的值即可。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>循环添加异步事件中的循环变量</title>
</head>
<body>
    <button>按钮0</button>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <script>
        var aBtn = document.getElementsByTagName('button');
        for(var i = 0; i < aBtn.length; i++) {
            aBtn[i].index = i;
            aBtn[i].onclick = function() {
                alert(this.index);
            };
        }
    </script>
</body>
</html>

利用闭包

通过一个立即执行函数来创建闭包。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>循环添加异步事件中的循环变量</title>
</head>
<body>
    <button>按钮0</button>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <script>
        var aBtn = document.getElementsByTagName('button');
        for(var i = 0; i < aBtn.length; i++) {
            (function(i){
                aBtn[i].onclick = function() {
                    alert(i);
                };
            })(i);
        }
    </script>
</body>
</html>

利用ES6中的let来创建变量形成闭包。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>循环添加异步事件中的循环变量</title>
</head>
<body>
    <button>按钮0</button>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <script>
        var aBtn = document.getElementsByTagName('button');
        for(let i = 0; i < aBtn.length; i++) {
            aBtn[i].onclick = function() {
                alert(i);
            };
        }
    </script>
</body>
</html>

(正文完)

如果您认为本文中存在问题或有任何不足之处,欢迎您在Github:Rivalsa/comment中提交issue

到底线啦,请:返回目录页|返回首页