如何删除addEventListener绑定的匿名函数,并将事件对象作为参数

时间:2016-11-18 02:23:34

标签: javascript

例如,

document.addEventListener('keyup',function(ev){
    if(ev.ctrlKey)dosomething();
},false);

有没有办法删除匿名函数?

4 个答案:

答案 0 :(得分:0)

您可以命名匿名函数并使用它来取消绑定

document.addEventListener('keyup',function handleKeyUp(ev){
    document.removeEventListener(ev.type, handleKeyUp);
    if(ev.ctrlKey)dosomething();
},false);

答案 1 :(得分:0)

您可以使用箭头功能调用函数并传递事件。



document.addEventListener('keyup',event => dosomething(event));
function dosomething(event){
    console.log("Test 1");
    event.currentTarget.removeEventListener(event.type, arguments.callee.caller);
}

/////////////////////////////////////
//OR
document.addEventListener('keyup', function(event){
    console.log("Test 2");
    event.currentTarget.removeEventListener(event.type, arguments.callee);
});




使用此实现还可以保留this

的范围
  

与函数表达式相比,箭头函数表达式具有更短的语法,并且不绑定它自己的this,arguments,super或new.target。箭头功能始终是匿名的。这些函数表达式最适合非方法函数,不能用作构造函数。

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

答案 2 :(得分:0)

在使用匿名功能时,无法从外部侦听器功能中删除该事件侦听器。虽然它可能在您的代码中显示为匿名,但它会被分配给某种变量,即使名称为listeners.keyup[3],它也会对其进行有效命名。

您可以使用arguments.callee 1 或从其调用的函数(如Zze's answer中所述)从事件侦听器本身中删除事件侦听器。 / p>

要使用EventTarget.removeEventListener()删除侦听器,您需要引用正在侦听的实际函数。您需要执行以下操作之一:

  • 命名函数。

    
    
    document.addEventListener('keyup',handleKeyupEvent,false);
    
    function handleKeyupEvent(ev) {
        if(ev.ctrlKey) {
            dosomething();
        } else {
            console.log('keyup event, no Ctrl key');
        }
    }
    
    function dosomething(){
        console.log('Ctrl key');
        document.removeEventListener('keyup',handleKeyupEvent,false);
    }
      
    
    
    

  • 将其分配给变量,该变量实际上是命名它 变量不必只是一个仅引用函数的变量(例如handleKeyupEvent)。例如,您可以将一个侦听器列表存储在Object或Array中(例如listeners.keyup[3])。当动态创建实际的侦听器功能时(例如,使用.bind()),这可能是有利的。

    
    
    handleKeyupEvent = function(ev) {
        if(ev.ctrlKey) {
            dosomething();
        } else {
            console.log('keyup event, no Ctrl key');
        }
    }
    
    document.addEventListener('keyup',handleKeyupEvent,false);
    
    function dosomething(){
        console.log('Ctrl key');
        document.removeEventListener('keyup',handleKeyupEvent,false);
    }
    
      
    
    
    

  • 使用arguments.callee 1

    从侦听器中访问它

    
    
      
        document.addEventListener('keyup',function(ev){
        if(ev.ctrlKey) {
            dosomething();
            ev.currentTarget.removeEventListener(ev.type, arguments.callee,false);
        } else {
            console.log('keyup event, no Ctrl key');
        }
    },false);
    
    function dosomething(){
        console.log('Ctrl key');
    }
      
      
    
    
    

  • 从侦听器使用Function.caller调用的函数访问它。

    
    
        document.addEventListener('keyup',function(ev){
        if(ev.ctrlKey) {
            dosomething(ev);
        } else {
            console.log('keyup event, no Ctrl key');
        }
    },false);
    
    function dosomething(ev){
        console.log('Ctrl key');
        ev.currentTarget.removeEventListener(ev.type, dosomething.caller,false);
    }
    
    
    

  • 以其他方式,存储对该函数的引用。

删除元素上的所有侦听器

对于常规元素(即不是<document>等),您可以有效地删除所有侦听器,但不能只删除一个。您可以充分操作DOM,例如删除该元素上的所有事件侦听器(或者创建元素的等效克隆)。最不具破坏性的是Node.cloneNode()元素,然后将当前元素替换为克隆,同时将原始的所有子元素附加到克隆(从而保留子元素及其后代上存在的任何事件处理程序)。 / p>

1。 MDN has this to say about using arguments.callee

  

警告:5th edition of ECMAScript (ES5)禁止在strict mode中使用arguments.callee()。避免使用arguments.callee()通过给函数表达式命名或使用函数声明,函数必须调用它自己。

基本上,最好只给函数一个名称,即使它在该函数表达式中只是有效:

document.addEventListener('keyup',function myFunctionName(ev){
    //myFunctionName is only valid within the function. You should use this type of
    //  name instead of using arguments.callee.
    if(ev.ctrlKey)dosomething();
},false);

答案 3 :(得分:0)

您可以自己为addEventListener写一个小界面,如下所示:

function addEventListener(elt, event, fn) {
  elt.addEventListener(event, fn);
  return function() {
    elt.removeEventListener(event, fn);
  };
}

这将返回一个函数,可用于删除事件侦听器,无论传递什么函数。

要使用它:

var remove = addEventListener(body, 'click', () => alert('Hi Mom'));

remove();

要在触发后立即删除事件侦听器,您只需要:

function addEventListenerOnce(elt, event, fn) {
  elt.addEventListener(event, function listener() {
    fn(e);
    elt.removeEventListener(elt, listener);
  });
}

或者,您可以使用在某些浏览器中实现的新{once: true}选项。