【问题标题】:Function call with parameters to addEventListener inside a loop [duplicate]带有参数的函数调用到循环内的addEventListener [重复]
【发布时间】:2015-08-01 23:08:21
【问题描述】:

问题:我想调用一个函数“test”并使用按钮的点击事件传递参数。

使用addEventListener ('click', test ); 有效。

使用addEventListener ('click', test(parameter));该功能在加载时自动激活,无需点击按钮。

问题:如何传递参数?

//create 3 button (n is a counter):
    var btn = document.createElement("INPUT");
        btn.setAttribute("id", "demo"+n);
        btn.setAttribute("type", "button");
        btn.setAttribute("value", ("click"));
        document.body.appendChild(btn);

无参数调用正常:

function test(m) {
    alert("YOU CLICKED ME!");
}

var m=0;
while(m!=3){
        document.getElementById("demo"+m).addEventListener("click", test);
        m=m+1;
}   

`

带参数不起作用(该功能立即激活):

function test(m) {
    alert("YOU CLICKED ME!"+m);
}

var m=0;
while(m!=3){
    document.getElementById("demo"+m).addEventListener("click", test(m));
            m=m+1;
}   

【问题讨论】:

    标签: javascript


    【解决方案1】:

    将您的函数包装在另一个函数中以避免立即调用它

    document.getElementById("demo"+m).addEventListener("click",(function(x){
        return function(){
            test(x);
        }
    })(m));
    

    在您的情况下, addEventListener 需要一个函数对象,因此您不能在函数前面使用括号,因为它调用函数并传递返回值。所以你需要返回调用测试函数的函数对象(使用匿名函数来避免javascript函数的闭包属性)

    编辑:使用匿名函数返回测试包装函数的原因

    我们不能通过

    function(){
        test(m);
    }
    

    直接添加EventListener。 由于 javascript 中的每个函数对象都会记住其词法范围之外的环境(in our case variable m)。如果您只是在同一环境(variable m)中创建不同的函数(例如在 while 循环中),那么它们将引用同一环境。

    如上所述,您有两个使用function factory to avoid creating closures in loop

    【讨论】:

    • 这将不起作用,您将始终拥有来自 m 中的循环的最后一个值。
    • 是的,忘记闭包了。谢谢修复
    【解决方案2】:

    解释为什么addEventListener('click', test(parameter)) 不起作用

    addEventListener 函数可以接受两个参数,一个事件类型和一个接收事件的侦听器对象。在大多数情况下,侦听器对象只是一个 JavaScript 函数。

    所以当你使用

    addEventListener('click', test);
    

    您将字符串 click 作为事件类型传递,并将函数 test 作为侦听器传递,这是您所期望的。

    但是当你使用时

    addEventListener('click', test(parameter));
    

    监听器实际上是表达式test(parameter) 计算的值。由于test(parameter) 是一个函数调用,因此您实际上传递了test(parameter) 返回的内容,在您的情况下为'undefined',因为test 函数不返回任何内容。这就是为什么立即调用 test 的原因 - 需要调用它来获取返回值作为 addEventListener 函数调用的参数。

    所以要在事件发生时执行带有自定义参数的函数,正如其他人建议的那样,您可以使用 匿名函数 方法。

    【讨论】:

      【解决方案3】:

      试试这个:

      function test(m) {
          alert("YOU CLICKED ME!"+m);
      }
      
      var m=0;
      while (m!=3) {
          (function(m) {
              document.getElementById("demo"+m).addEventListener("click", function() {
                  test(m);
              });
          })(m);
          m=m+1;
      }   
      

      这将为循环内部的变量创建新范围。

      【讨论】:

        【解决方案4】:

        您需要使用所谓的“高阶函数”构建test 函数的版本:

        // this is a high order function, since it returns a function
        function buildTestFunction(m) {
          return function () {
            alert("YOU CLICKED ME!"+m);
          };
        }
        
        var m=0;
        while(m!=3){
          var test = buildTestFunction(m);
          document.getElementById("demo"+m).addEventListener("click", test);
          m=m+1;
        }
        

        附言。为了清楚起见,您可能想在此处使用for 循环。

        for (var m = 0; m < 3; m++) { ... }
        

        【讨论】:

          猜你喜欢
          • 2021-01-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多