Можно ли удалить EventListener, аннулировав его функцию обратного вызова?

#javascript #firefox-addon

#javascript #firefox-дополнение

Вопрос:

Мне было интересно, можно ли удалить прослушиватель событий, аннулировав его функцию обратного вызова?

Упрощенный пример:

 var somefunction = function() {
  // some code
}
window.addEventListener(eventType, somefunction, false); 
  

Теперь, будет ли установка somefunction = null; удалять вышеупомянутый EventListener или он просто превратит его в список событий зомби?

Фактический код используется в Firefox (overlay-type) Аддон и я рассматривали альтернативные методы (автоматического) удаления EventListeners при unload событии, отличные от очевидных:

 window.removeEventListener(eventType, somefunction, false); 
  

Обновление: Пожалуйста, обратите внимание, что это часть кода для дополнения Firefox. Тип события в этом экземпляре 'popupshowing' не может быть обнулен, поскольку это нарушит функции браузера.

Заранее благодарим вас за помощь с нетерпением ждем (альтернативных) предложений

Комментарии:

1. я не думаю, что установка функции обратного вызова в значение null приведет к удалению eventlistener, но установка EventType = null (в вашем случае) должна удалить прослушиватель событий

2. Спасибо. Я добавлю пояснения к исходному сообщению.

Ответ №1:

removeEventListener это путь.

Кроме того, вы на самом деле не обнуляете функцию, устанавливая некоторую переменную в null . Переменной назначена только ссылка (на объект, не являющийся POD, например, на функцию). Чтобы проиллюстрировать это, рассмотрим следующее:

 var a = function() { alert("called"); };
setTimeout(a, 1000); // Will still alert!

var b = a;

a = null; // What you called `nullify`....
console.log(this.a, "a" in this); // null, true
delete this.a; // Actually remove the property from the global scope.
// `a` is really dead at this point!

b(); // will still alert, too.
  

Если вы хотите избежать некоторых removeEventListener вызовов, я бы использовал некоторые вспомогательные функции:

 let { addEventListenerUnload, removeEventListenerUnload } = (function() {
  let tracked = [];
  addEventListener("unload", function removeTracked() {
    removeEventListener("unload", removeTracked);
    for (let t of tracked) {
      try {
        removeEventListener(t.type, t.fn, t.capture);
      }
      catch (ex) {}
    }
    tracked.length = 0;
  });
  return {
    addEventListenerUnload: function(type, fn, capture) {
      addEventListener(type, fn, capture);
      tracked.push({type: type, fn: fn, capture: capture});
    },
    removeEventListenerUnload: function(type, fn, capture) {
      tracked = tracked.filter(e => e.type != type || e.fn != fn || e.capture != capture);
      removeEventListener(type, fn, capture);
    }
  };
})();
  

(Включает в себя некоторые материалы ECMA-6, которые поддерживает Firefox, но которые вы могли бы легко преобразовать. Кроме того, removeEventListenerUnload это может вообще не понадобиться, поэтому вы можете его опустить. Кроме того, при использовании этого в скрипте наложения обязательно присваивайте ему уникальные имена, чтобы избежать столкновений с другим кодом).

Комментарии:

1. Спасибо за ваше объяснение. На самом деле, я создаю массив объектов (по одному для каждого слушателя, перечисляющего его параметры) и использую его позже removeEventListener , и он работает (хотя его производительность трудно измерить unload , но я хотел еще больше упростить его, изучив другие возможности. 🙂

2. Вы знаете, обычный способ поблагодарить людей здесь, на SO, — это проголосовать и / или принять их ответы… Просто говорю 😉 Но, пожалуйста, не воспринимайте это как просьбу проголосовать за мой конкретный ответ здесь: Конечно, вы можете голосовать по своему усмотрению.

3. Сделает это немедленно 🙂

Ответ №2:

я не думаю, что установка функции обратного вызова в значение null приведет к удалению eventlistener, у вас все равно будет прикреплен eventlistener, вы можете использовать removeEventListener или установить значение eventType null, например:

 window.eventType = null;
  

Комментарии:

1. Спасибо. Я добавлю пояснения к исходному сообщению. 🙂