removeEventListener на анонимных функциях в JavaScript


у меня есть объект, который имеет методы в нем. Эти методы помещаются в объект внутри анонимной функции. Выглядит это так:

var t = {};
window.document.addEventListener("keydown", function(e) {
    t.scroll = function(x, y) {
        window.scrollBy(x, y);
    };
    t.scrollTo = function(x, y) {
        window.scrollTo(x, y);
    };
});  

(существует гораздо больше кода, но этого достаточно, чтобы показать проблему)

теперь я хочу остановить прослушиватель событий в некоторых случаях. Поэтому я пытаюсь сделать removeEventListener, но я не могу понять, как это сделать. Я прочитал в других вопросах, что невозможно вызвать removeEventListener на anonymous функции, но это также имеет место в этой ситуации?

у меня есть метод в t, созданный внутри анонимной функции, и поэтому я думал, что это возможно. Выглядит так:

t.disable = function() {
    window.document.removeEventListener("keydown", this, false);
}

почему я не могу сделать это?

есть ли другой (хороший) способ сделать это?

Бонусная информация; это должно работать только в Safari, следовательно, отсутствует поддержка ie.

11 66

11 ответов:

Я считаю, что это точка анонимной функции, ей не хватает имени или способа ссылаться на нее.

на вашем месте я бы просто создал именованную функцию или поместил ее в переменную, чтобы у вас была ссылка на нее.

var t = {};
var handler = function(e) {
    t.scroll = function(x, y) {
        window.scrollBy(x, y);
    };
    t.scrollTo = function(x, y) {
        window.scrollTo(x, y);
    };
};
window.document.addEventListener("keydown", handler);

затем вы можете удалить его с помощью

window.document.removeEventListener("keydown", handler);   

Если вы находитесь внутри фактической функции, вы можете использовать аргументы.вызываемый объект в качестве ссылки на функцию. как в:

button.addEventListener('click', function() {
      ///this will execute only once
      alert('only once!');
      this.removeEventListener('click', arguments.callee);
});

EDIT: Это не будет работать, если вы работаете в строгом режиме ("use strict";)

версия Отто Nascarellaрешение, которое работает в строгом режиме:

button.addEventListener('click', function handler() {
      ///this will execute only once
      alert('only once!');
      this.removeEventListener('click', handler);
});
window.document.removeEventListener("keydown", getEventListeners(window.document.keydown[0].listener));  

может быть несколько анонимных функций, keydown[1]

не очень анонимный вариант

element.funky = function() {
    console.log("Click!");
};
element.funky.type = "click";
element.funky.capt = false;
element.addEventListener(element.funky.type, element.funky, element.funky.capt);
// blah blah blah
element.removeEventListener(element.funky.type, element.funky, element.funky.capt);

С момента получения обратной связи от Энди (совершенно верно, но как и во многих примерах, я хотел показать контекстуальное расширение идеи) здесь менее сложным экспозиция:

<script id="konami" type="text/javascript" async>
    var konami = {
        ptrn: "38,38,40,40,37,39,37,39,66,65",
        kl: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
    };
    document.body.addEventListener( "keyup", function knm ( evt ) {
        konami.kl = konami.kl.slice( -9 );
        konami.kl.push( evt.keyCode );
        if ( konami.ptrn === konami.kl.join() ) {
            evt.target.removeEventListener( "keyup", knm, false );

            /* Although at this point we wish to remove a listener
               we could easily have had multiple "keyup" listeners
               each triggering different functions, so we MUST
               say which function we no longer wish to trigger
               rather than which listener we wish to remove.

               Normal scoping will apply to where we can mention this function
               and thus, where we can remove the listener set to trigger it. */

            document.body.classList.add( "konami" );
        }
    }, false );
    document.body.removeChild( document.getElementById( "konami" ) );
</script>

Это позволяет эффективно анонимную структуру функции, избегает использования практически устаревший callee, и позволяет легко удаление.

кстати: удаление элемента скрипта сразу после установки слушателя-это симпатичный трюк для скрытия кода, который предпочел бы не был совершенно очевиден для посторонних глаз ( испортил бы сюрприз ; -)

поэтому метод (проще) составляет:

element.addEventListener( action, function name () {
    doSomething();
    element.removeEventListener( action, name, capture );
}, capture );

Это не идеально, так как он удаляет все, но может работать для ваших нужд:

z = document.querySelector('video');
z.parentNode.replaceChild(z.cloneNode(1), z);

клонировать узел копирует все его атрибуты и их значения, в том числе встроенные (встроенные) слушатели. Он не копирует прослушиватели событий, добавленные с помощью addEventListener ()

узел.cloneNode ()

JavaScript: addEventListener метод регистрирует указанный прослушиватель на EventTarget (элемент|документ|окно), который он вызывает.

EventTarget. addEventListener(тип, handler_function,Клокотать|Захвата);

Мышь, Клавиатура событий пример теста в WebConsole:

var keyboard = function(e) {
    console.log('Key_Down Code : ' + e.keyCode);
};
var mouseSimple = function(e) {
    var element = e.srcElement || e.target;
    var tagName = element.tagName || element.relatedTarget;
    console.log('Mouse Over TagName : ' + tagName);    
};
var  mouseComplex = function(e) {
    console.log('Mouse Click Code : ' + e.button);
} 

window.document.addEventListener('keydown',   keyboard,      false);
window.document.addEventListener('mouseover', mouseSimple,   false);
window.document.addEventListener('click',     mouseComplex,  false);

removeEventListener метод удаляет прослушиватель событий, ранее зарегистрированный в EventTarget.addEventListener ().

window.document.removeEventListener('keydown',   keyboard,     false);
window.document.removeEventListener('mouseover', mouseSimple,  false);
window.document.removeEventListener('click',     mouseComplex, false);

caniuse

чтобы дать более современный подход к этому:

//one-time fire
element.addEventListener('mousedown', {
  handleEvent: function (evt) {
    element.removeEventListener(evt.type, this, false);
  }
}, false);

возможно, не лучшее решение с точки зрения того, что вы просите. Я все еще не определил эффективный метод для удаления анонимной функции, объявленной в строке с вызовом прослушивателя событий.

Я лично использую переменную для хранения <target> и объявить функцию вне вызова прослушивателя событий, например:

const target = document.querySelector('<identifier>');

function myFunc(event) { function code; }

target.addEventListener('click', myFunc);

затем удалить слушатель:

target.removeEventListener('click', myFunc);

Не самая лучшая рекомендация, которую вы получите, но для удаления анонимных функций единственное решение, которое я нашел полезным, - это удалить, а затем заменить элемент HTML. Я уверен, что должен быть лучший метод vanilla JS, но я его еще не видел.

я наткнулся на ту же проблему, и это было лучшее решение, я мог бы получить:

/*Adding the event listener (the 'mousemove' event, in this specific case)*/
element.onmousemove = function(event) {
    /*do your stuff*/
};
/*Removing the event listener*/
element.onmousemove = null;

пожалуйста, имейте в виду, что я только проверил это для window элемент и 'mousemove' событие, поэтому могут быть некоторые проблемы с этим подходом.

window.document.onkeydown = function(){};