for循环语句实现指定按钮动作下的指定对话框

希望通过for循环语句实现指定按钮动作下的指定对话框,例如one按钮直接弹出one对话框,two按钮直接弹出two对话框,希望使用循环语句,不用一条一条地列出,代码地址为以下链接

阅读 3.4k
3 个回答
func = function(text) { return function() { alert(text) } };
for(var num = 0; num < btn.length; num++) {
    btn[num].onclick = func(array[num]);
}

问题的根源

变量提升现象

window.onload = function(){
    var body = document.getElementsByTagName('body')[0];
    var btn = document.getElementsByTagName('button');
    var array = ['one','two','three','four','five'];
    
    for(var num = 0;num<btn.length;num++) {
        btn[num].onclick = function () {
            console.log(num)
        }
    }
}

因为onclick是在浏览器触发其事件的时候才会执行,因此他是一个异步执行的函数,无论如何都会在这段代码执行完成之后才会执行,而此时javascript已经完成了这段代码的for循环,num的值也早就变成了btn.length-1了,这种现象叫做变量提升

解决方法

  • 方法1,使用bind方法产生一个绑定参数而且延时执行的方法

for(var num = 0;num<btn.length;num++) {
    btn[num].onclick = (function (n,e) {
        console.log(n);
        console.log(array[n])
    }).bind(this, num);
    //使用bind把函数柯里化,注意的是bind会产生一个新的方法,注意此时原有的event参数会到第二个参数
}

-方法2,创建一个创建一个新的函数并用其作用域参数保存num值,防止变量提升,(闭包)

for(var num = 0;num<btn.length;num++) {
    btn[num].onclick = (function (n) {
       return function (e){
           console.log(n);
           console.log(array[n])
       }
    })(num)
}

-方法3,let关键字,可以在nodejs用于解决变量提升,支持let的浏览器也可以一战(MS Edge、Chrome等)

for(var num = 0;num<btn.length;num++) {
    let n = num; //let关键字生成的变量只会在当前{}代码块中,不会产生变量提升现象
    btn[num].onclick = function (e) {
       console.log(n);
       console.log(array[n])
    }
}
  1. 循环+闭包

  2. 事件代理

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>quick-start</title>
    <style>
    </style>
    <script>
        window.onload = function(){
            var body = document.getElementsByTagName('body')[0];
            var btn = document.getElementsByTagName('button');
            var array = ['one','two','three','four','five'];
            
            //2.事件代理机制
            /*
            body.addEventListener('click',function(event){
                var index=0;
                if(event.target.tagName.toLowerCase()==='button'){
                    index=Array.prototype.indexOf.call(btn,event.target);
                    console.log(array[index]);
                }
            },false);
            */
            
            //1. 闭包+循环
            for(var num = 0;num<btn.length;num++){
                (function(element,data){
                    element.onclick = function(){
                        console.log(data);
                    }
                }(btn[num],array[num]));

            }

        }
    </script>
</head>
<body>
    <button>one</button>
    <button>two</button>
    <button>three</button>
    <button>four</button>
    <button>five</button>
</body>

</html>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏