如何使用函数动态定义javascript事件处理程序

如何使用函数动态定义javascript事件处理程序,javascript,function,scope,Javascript,Function,Scope,我对Javascript有点陌生,我似乎不知道我的函数到底发生了什么 背景:我的脚本应该允许您将一个“toggler”或“toggled”类分配给元素,以使它们自动链接,因此选中/取消选中toggler将显示/隐藏切换(我知道有许多库可以这样做,但不幸的是,在这种情况下我不能使用它们) 脚本在pageload上执行,并在元素中搜索类为“toggler”的元素,然后相应地分配其onclick处理程序。以下是我遇到问题的代码: function makeToggle () { for (

我对Javascript有点陌生,我似乎不知道我的函数到底发生了什么

背景:我的脚本应该允许您将一个“toggler”或“toggled”类分配给元素,以使它们自动链接,因此选中/取消选中toggler将显示/隐藏切换(我知道有许多库可以这样做,但不幸的是,在这种情况下我不能使用它们)

脚本在pageload上执行,并在元素中搜索类为“toggler”的元素,然后相应地分配其onclick处理程序。以下是我遇到问题的代码:

  function makeToggle () {
    for (i=0;i<toggler.length;i++) { 
      toggler[i].onclick=function(){toggleSection(this,i)};
    }
  }

  function toggleSection(obj,index) {
    if (obj.checked==true) {
      toggled[index].style.display="inline-block";
    } else {
      toggled[index].style.display="none";
    }
  }
它们的实际设置(假设我有5个元素定义为切换器)是:


从我所读到的内容来看,我认为这是一个范围问题,或者是我调用函数的方式,但是我发现没有什么是有意义的

在创建函数时不能像那样使用变量I。如果这样做,i的值将是i的最后一个值。在您的问题中,i将始终是切换器的长度

因此,您应该将变量(i)作为参数传递给onclick函数

试着这样,

function makeToggle () {
    for (i=0;i<toggler.length;i++) { 
      toggler[i].addEventListener("click", (function(d) { return function(){ 
                    toggleSection(this,d);
      }; })(i), true);
    }
}
函数makeToggle(){

对于(i=0;i,您将看到中详述的问题

原因相当复杂。我们定义为事件处理程序的匿名函数“继承”了attachEventsToListItems范围内的变量i,而不是for循环。但是,在执行事件处理程序时,for循环已完成其迭代,并且此函数中的i值已变为4。这里的问题是我们定义为事件处理程序的函数在执行之前不会为i创建新的作用域

要解决此问题,您需要关闭:

for (i=0;i<toggler.length;i++) { 
    toggler[i].onclick= (function (index) {
        return function() {
            toggleSection(this,index);
        };
    }) (i);
}

for(i=0;iOcanal写的是正确的。我创建了JSFIDLE示例来展示差异。哇,谢谢大家。非常有用的答案。jbabey给我的链接帮助我指出了正确的方向,学习明智。再次感谢!@ctshiner您应该接受/投票解决您的问题的答案;)所有的答案都非常有帮助。jbabey的答案是公认的,因为它通过一点解释更深入地了解了实际发生的事情。这是帮助理解闭包的好链接
function makeToggle () {
    for (i=0;i<toggler.length;i++) { 
      toggler[i].addEventListener("click", (function(d) { return function(){ 
                    toggleSection(this,d);
      }; })(i), true);
    }
}
function makeToggle () {
    for (i=0;i<toggler.length;i++) { 
       toggler[i].onclick = (function(d) { return function(){toggleSection(this,d)}})(i);
    }
}
for (i=0;i<toggler.length;i++) { 
    toggler[i].onclick= (function (index) {
        return function() {
            toggleSection(this,index);
        };
    }) (i);
}