Javascript ';这';在回调中,通过apply绑定为闭包,如果按特定顺序调用,则apply将变得未定义

Javascript ';这';在回调中,通过apply绑定为闭包,如果按特定顺序调用,则apply将变得未定义,javascript,callback,closures,apply,Javascript,Callback,Closures,Apply,我有一个JS函数,我尝试使用这个,它应该是点击按钮来触发函数: function myAction( greeting ) { console.log( greeting + ", the button is :" + this ); this.remove(); } 然后,我的页面上有几个按钮,比如说两个(这甚至在页面上只有两个按钮的情况下发生;我已经测试过了): 我对这种方法从来没有任何问题;它总是有效的。这真的是错误的方法吗 因为,我现在面对的是,当我点击按钮一,然后

我有一个JS函数,我尝试使用
这个
,它应该是点击按钮来触发函数:

function myAction( greeting ) { console.log( greeting + ", the button is :" + this ); this.remove(); }
然后,我的页面上有几个按钮,比如说两个(这甚至在页面上只有两个按钮的情况下发生;我已经测试过了):

我对这种方法从来没有任何问题;它总是有效的。这真的是错误的方法吗

因为,我现在面对的是,当我点击按钮一,然后点击按钮二,这实际上在严格模式下是未定义的,而窗口在非严格模式下是未定义的;在第二次单击时。当我以另一种方式进行操作时,
这个
始终是相应单击的按钮。它似乎以某种方式更新了
myButtons
集合,这样,当第一个按钮通过第一次调用被移除时,
1
索引在集合中变得不可用,因为只有一个剩余按钮;另一个正在移除。至少这是我的理论。但我以前从未在类似的代码案例中遇到过这个问题?那么我该如何编码我想发生的事情呢

编辑

感谢你们所有人;特别感谢@Nenad Vracar,因为他的解决方案通过简单地更改以下内容,实现了所需的最少编辑,使之完美工作:

var myButtons = document.getElementsByClassName( "click-me" );
var amountOfButtons = myButtons.length;
for ( var i = 0; i < amountOfButtons; i++ ) {
    myButtons[i].addEventListener( "click", (
      function(i) {
        return function() { myAction.apply( myButtons[i], ["hello"] ); };
      }(i))
    );
  }
var myButtons=document.getElementsByClassName(“单击我”);
var amountOfButtons=myButtons.length;
对于(变量i=0;i
致:

var myButtons=document.getElementsByClassName(“单击我”);
var amountOfButtons=myButtons.length;
对于(变量i=0;i
简单聪明的解决方案,我简直看不到树木的树木!再次感谢


注意。事件委派在这里并不是一个真正的选项,因为页面/需要附件的元素的DOM结构有些复杂,我通常更喜欢将函数附加到需要它的元素上。另外,我不希望将函数的代码更改为闭包本身,也不希望对函数代码本身进行更改。因此,我决定使用此解决方案。

您可以使用稍微不同的方法,使用
querySelectorAll
,然后使用
forEach
循环。在点击事件处理程序中,您不需要额外的闭包,
myAction
中的
this
将是点击事件处理程序中的
this
,因为您将它作为
thisArg
参数传递给
apply

功能myAction(问候语){
console.log(问候语+),按钮为:“+this.textContent”;
这个。删除();
}
文件
.querySelectorAll(“单击我”)
.forEach(功能(btn){
btn.addEventListener('click',function(){
myAction.apply(这个,['Hello']))
})
})
1

两个
您目前的方法似乎非常复杂。这里有两个简化流程的建议

高阶函数事件处理程序 如果将
myAction
重新定义为返回事件侦听器的函数,则可以直接传递参数。因此,在分配处理程序时,无需将其包装到另一个函数中:

函数myAction(问候语){//接受输入
return function(){//返回充当事件侦听器的函数
log(greeting+),按钮是:“+this”;this.remove();
}
}
var myButtons=document.getElementsByClassName(“单击我”);
var amountOfButtons=myButtons.length;
对于(变量i=0;i
点击我

单击我
我认为不需要在生命中的回调中对回调进行复杂的包装<代码> MyButo[i]。AdvestListEnter(MyActudio,MyActudio([您好)])/代码>如果您将事件侦听器定义为一个高阶函数,返回一个无参数函数,就足够了。此外,考虑使用事件委托,而不是单独地将事件监听器附加到每个元素。只需使用传递给作为参数传递给
addEventListener
的所有函数的事件参数,并使用
event.target
,而不用担心
这个问题。您也可以传递事件,以便在myAction中访问它,就像这样,这个答案导致了我认为最简单的解决方案/毕竟最不需要的编辑;谢谢你,伙计!非常感谢您提供的解决方案和所有解释;我只是接受了下面的答案,因为这似乎是我案例中最简单的方法(见我的编辑)。但是非常感谢你,伙计!
var myButtons = document.getElementsByClassName( "click-me" );
var amountOfButtons = myButtons.length;
for ( var i = 0; i < amountOfButtons; i++ ) {
    myButtons[i].addEventListener( "click", (
      function(i) {
        return function() { myAction.apply( myButtons[i], ["hello"] ); };
      }(i))
    );
  }
var myButtons = document.getElementsByClassName( "click-me" );
var amountOfButtons = myButtons.length;
for ( var i = 0; i < amountOfButtons; i++ ) {
    myButtons[i].addEventListener( "click", (
      function(i) {
        return function() { myAction.apply( myButtons[i], ["hello"] ); };
      }(i))
    );
  }
var myButtons = document.getElementsByClassName( "click-me" );
var amountOfButtons = myButtons.length;
for ( var i = 0; i < amountOfButtons; i++ ) {
    myButtons[i].addEventListener( "click", function() {
      myAction.apply( this, ["hello"] );
    });
  }