Подтвердить что ты не робот

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 для анонимных функций, но так ли это в этой ситуации?

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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);   

Ответ 2

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

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

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

Ответ 3

Версия Отто Наскарелла, работающая в строгом режиме:

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

Ответ 4

window.document.removeEventListener("keydown", getEventListeners(window.document.keydown[0].listener));  

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

Предупреждение: работает только в Chrome Dev Tools и не может использоваться в коде: ссылка

Ответ 5

Не анонимный вариант

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>

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

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

Таким образом, метод (проще):

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

Ответ 6

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

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

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

Node.cloneNode()

Ответ 8

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

EventTarget. addEventListener (event_type, handler_function, Bubbling | Capturing);

Мышь, клавиатура события Пример теста в 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

Ответ 9

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

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

Ответ 10

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

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

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

function myFunc(event) { function code; }

target.addEventListener('click', myFunc);

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

target.removeEventListener('click', myFunc);

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

Ответ 11

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

/*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', поэтому при таком подходе могут возникнуть некоторые проблемы.

Ответ 12

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