Как найти слушателей событий на узле DOM при отладке или из кода JavaScript?

У меня есть страница, на которой некоторые прослушиватели событий прикреплены к полям ввода и полям выбора. Есть ли способ узнать, какие прослушиватели событий наблюдают за конкретным узлом DOM и для какого события?

События прикрепляются с использованием:

  1. ПрототипаEvent.observe;
  2. DOM's addEventListener;
  3. Как атрибут элемента element.onclick.

Как связаны события в первую очередь? Вы используете библиотеку (например, Prototype, jQuery и т. д.)?

Crescent Fresh 15.01.2009 18:07

Важно отметить, что несколько функций обратного вызова могут быть прикреплены для одного и того же типа события через element.addEventListener(type, callback, [bubble]), тогда как element.onclick = function будет перезаписывать каждый раз, когда вы назначаете.

Braden Best 11.05.2017 02:13

Получает все события вместе с их соответствующим элементом: Array.from(document.querySelectorAll("*")).forEach(e => { const ev = getEventListeners(e); if (Object.keys(ev).length !== 0) {console.info(e, ev)} })

Gabriel Petersson 22.07.2020 17:23

Вы можете захватить addEventListener и захватить список всех слушателей в элементе DOM. Вот пример кода stackoverflow.com/a/64484951/1812732

John Henckel 22.10.2020 18:00
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
901
4
614 506
19
Перейти к ответу Данный вопрос помечен как решенный

Ответы 19

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

var handler = function() { alert('clicked!') };

Мы собираемся прикрепить его к нашему элементу, используя разные методы, некоторые из которых позволяют проверку, а некоторые - нет.

Метод A) обработчик одиночного события

element.onclick = handler;
// inspect
console.info(element.onclick); // "function() { alert('clicked!') }"

Метод б) несколько обработчиков событий

if (element.addEventListener) { // DOM standard
    element.addEventListener('click', handler, false)
} else if (element.attachEvent) { // IE
    element.attachEvent('onclick', handler)
}
// cannot inspect element to find handlers

Метод C): jQuery

$(element).click(handler);
  • 1.3.x

     // inspect
     var clickEvents = $(element).data("events").click;
     jQuery.each(clickEvents, function(key, value) {
         console.info(value) // "function() { alert('clicked!') }"
     })
    
  • 1.4.x (хранит обработчик внутри объекта)

     // inspect
     var clickEvents = $(element).data("events").click;
     jQuery.each(clickEvents, function(key, handlerObj) {
         console.info(handlerObj.handler) // "function() { alert('clicked!') }"
         // also available: handlerObj.type, handlerObj.namespace
     })
    
  • 1.7+ (очень красиво)

    Сделано с использованием знаний от этот комментарий.

     events = $._data(this, 'events');
     for (type in events) {
       events[type].forEach(function (event) {
         console.info(event['handler']);
       });
     }
    

(See jQuery.fn.data and jQuery.data)

Метод D): прототип (беспорядочный)

$(element).observe('click', handler);
  • 1.5.x

     // inspect
     Event.observers.each(function(item) {
         if (item[0] == element) {
             console.info(item[2]) // "function() { alert('clicked!') }"
         }
     })
    
  • С 1.6 по 1.6.0.3 включительно (тут очень сложно стало)

     // inspect. "_eventId" is for < 1.6.0.3 while 
     // "_prototypeEventID" was introduced in 1.6.0.3
     var clickEvents = Event.cache[element._eventId || (element._prototypeEventID || [])[0]].click;
     clickEvents.each(function(wrapper){
         console.info(wrapper.handler) // "function() { alert('clicked!') }"
     })
    
  • 1.6.1 (немного лучше)

     // inspect
     var clickEvents = element.getStorage().get('prototype_event_registry').get('click');
     clickEvents.each(function(wrapper){
         console.info(wrapper.handler) // "function() { alert('clicked!') }"
     })
    

При щелчке по результирующему выводу в консоли (которая показывает текст функции) консоль перейдет непосредственно к строке объявления функции в соответствующем файле JS.

Спасибо за обновление. К сожалению, вам приходится перебирать каждый тип обработчика.

Keith Bentrup 14.09.2009 22:35

В «Методе B» (addEventListener) вот ответ относительно статуса средств перечисления для обработчиков, зарегистрированных с помощью чистого API событий DOM: stackoverflow.com/questions/7810534/…

Nickolay 19.10.2011 03:00

@John: спасибо за комментарий. У вас есть пример «настоящего JavaScript» для получения слушателей, ранее добавленных через addEventListener?

Crescent Fresh 25.04.2012 05:23

Если кто-то неаккуратен, он может создать службу мониторинга. Если у них есть хорошие практики, им просто не нужно их создавать. Те же слушатели перезаписывают старые версии самих себя.

John 25.04.2012 21:23

@Jan, похоже, это не работает для jQuery 1.7.2, есть ли другой подход для этой версии?

tomdemuyt 30.05.2012 22:26

А как насчет прослушивателей событий, которых нет в фактическом элементе, например $(parentElement).on(event, 'myElement', handler);?

Aaron 12.01.2013 22:24

Почему существует так много способов привязать события и так много мест, где их можно сохранить? Нам, программистам, это не очень помогает, не так ли?

Rolf 12.01.2014 13:06

@tomdemuyt В jQuery события теперь хранятся во внутреннем массиве данных, а не доступны через .data('events'), как раньше. Для доступа к внутренним данным событий используйте $._data(elem, 'events'). Обратите внимание, что эта функция помечена как «только для внутреннего использования» в источнике jQuery, поэтому нет никаких обещаний, что она всегда будет работать в будущем, но я считаю, что она работала с момента выхода jQuery 1.7 и все еще работает.

Matt Browne 13.02.2014 20:17

@MattBrowne Очень мило. Я добавил его к ответу как полное решение.

mbomb007 26.09.2020 00:46

Если у вас есть Firebug, вы можете использовать console.dir(object or array) для печати красивого дерева в журнале консоли любого скаляра, массива или объекта JavaScript.

Пытаться:

console.dir(clickEvents);

или же

console.dir(window);

Новая функция в firebug 1.12 getfirebug.com/wiki/index.php/GetEventListeners

Javier Constanzo 31.08.2013 19:31
Ответ принят как подходящий

Если вам просто нужно проверить, что происходит на странице, вы можете попробовать букмарклет Визуальное событие.

Обновлять: Визуальное событие 2 доступен.

Идеально! Превосходит плагин EventBug от Firebug.

Robin Maben 15.09.2011 12:47

Это добавляет на страницу миллиард элементов, многие из которых являются изображениями. Его полезность значительно снижается на странице с множеством обработчиков событий (у меня 17k, а загрузка Visual Event заняла около 3 минут).

Tony R 09.03.2012 01:57

Я считаю, что упомянутое расширение Chrome @ssharma - это тот, который доступен здесь

kmote 17.02.2013 23:57

Визиальное событие не работает, если страница ссылается на стороннюю библиотеку js. Вызывает ошибку: XMLHttpRequest не может загрузить A.com/js/jquery-ui-1.10.3.custom.js?_=1384831682813. Источник B.com не разрешен Access-Control-Allow-Origin.

hiway 19.11.2013 07:50

Это очевидно из источника, но букмарклет внедряет на ваш сайт сторонний скрипт. Это может быть хорошо для большинства случаев, но если вы имеете дело с данными PCI, HIPAA и т. д., Вам, вероятно, следует держаться подальше.

ken 12.12.2013 00:45

Внутренние инструменты разработчика Chrome и FF (F12) имеют встроенную программу просмотра событий! Chrome: на вкладке «Элементы» выберите и элемент и посмотрите, что справа есть: Стиль, Вычисленный, Слушатели событий.

oriadam 31.12.2015 08:27

Кажется, что Visual Event не поддерживает способ добавления EventListeners в DOM 2. Для меня это крайне странно и непонятно, поскольку поддерживает полдюжины неосновных библиотек.

doABarrelRoll721 20.02.2016 05:11

@oriadam Замечательно! Есть ли способ определить, какой из них я хочу посмотреть быстрее, чем открывать их по очереди?

Michael 21.05.2016 00:40

В @Michael Firefox есть этот маленький значок «ev» рядом с элементами, у которых есть прослушиватели событий. Мне не удалось найти похожий значок в Chrome, извините. doABarrelRoll721 Если вы найдете способ их обнаружить, очень легко добавить синтаксический анализатор событий в библиотеку Visual Event. Заходите, код отличный :)

oriadam 22.05.2016 01:17

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

Legends 05.11.2016 15:47

@TonyR, вы пришли искать визуализатор событий и жалуетесь, потому что загрузка 17k событий занимает 3 минуты? Я имею в виду, что могу создать AI VisualEvent, который будет смотреть на ваши события и улавливать только те, которые вам понадобятся в это конкретное время, только если вы хотите ...

Justin Farrugia 02.08.2019 13:01

В чем разница между визуальным событием и визуальным событием 2?

Elijah Mock 08.12.2019 02:40

WebKit Inspector в браузерах Chrome или Safari теперь делает это. Он отобразит прослушиватели событий для элемента DOM, когда вы выберете его на панели «Элементы».

Я не уверен, что он показывает все обработчиков событий; только единственный обработчик событий HTML.

huyz 25.07.2011 12:21

Для полноты картины я должен упомянуть плагин EventBug для Firebug <softwareishard.com/blog/category/eventbug>

Nickolay 19.10.2011 02:59

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

siliconrockstar 19.12.2013 21:41

Можно перечислить всех слушателей событий в JavaScript: это не так уж сложно; вам просто нужно взломать метод prototype элементов HTML (перед добавляет слушателей).

function reportIn(e){
    var a = this.lastListenerInfo[this.lastListenerInfo.length-1];
    console.info(a)
}


HTMLAnchorElement.prototype.realAddEventListener = HTMLAnchorElement.prototype.addEventListener;

HTMLAnchorElement.prototype.addEventListener = function(a,b,c){
    this.realAddEventListener(a,reportIn,c); 
    this.realAddEventListener(a,b,c); 
    if (!this.lastListenerInfo){  this.lastListenerInfo = new Array()};
    this.lastListenerInfo.push({a : a, b : b , c : c});
};

Теперь каждый элемент привязки (a) будет иметь свойство lastListenerInfo, которое содержит всех его слушателей. И это даже работает для удаления слушателей с анонимными функциями.

Этот метод не будет работать, если вы пишете пользовательский сценарий или сценарий содержимого. В наши дни не только могут быть изолированы в песочнице, но и как гарантировать порядок выполнения?

huyz 25.07.2011 12:22

этот метод работает с chrome / 19 и FF / 12. порядок выполнения может быть гарантирован, если вы подключите его до других скриптов

Tzury Bar Yochay 01.06.2012 09:54

Не могли бы вы вместо этого просто модифицировать Node.prototype? Вот откуда HTMLAnchorElement в любом случае наследует .addEventListener ».

Esailija 16.06.2012 10:48

Вы предполагаете, что пользовательский агент реализует наследование прототипов для хост-объектов DOM и позволяет вам изменять их. Ни одна из этих идей не является хорошей: не изменяйте объекты, которыми вы не владеете.

RobG 13.11.2012 04:43

Это довольно бесполезно - оно показывает, какие слушатели событий были добавлены, что может быть полезно в некоторых случаях, но не то, что было удалено. Так что, если вы пытаетесь отладить, что было удалено, а что нет, просто нет способа.

gotofritz 15.09.2015 13:46

@gotofritz прав. Это не показывает вам прослушивателей событий, которые у вас есть на данный момент. Интересно, читали ли поддерживающие вообще вопрос.

doABarrelRoll721 20.02.2016 07:48

@ doABarrelRoll721 И мне интересно, есть ли у вас здравый смысл. Видите ли, JavaScript выполняется на стороне браузера, поэтому вы можете выполнить его в любой момент, когда захотите, например с небольшой помощью tamper-monkey вы можете запускать на всех веб-сайтах, которые вы открываете.

Ivan Castellanos 21.02.2016 02:51

@IvanCastellanos Я имел в виду, что ваш массив lastListenerInfo содержит только добавленные слушатели. OP запросил какие слушатели событий наблюдают за конкретным узлом DOM, включая те, которые были удаленный. Если бы вы перезаписали removeEventListener так же, как и с addEventListener, ваш массив lastListenerInfo будет иметь именно то, что просил OP (хотя он говорил о вводе и выборе элементов, а не о якорях, а о чем угодно).

doABarrelRoll721 21.02.2016 04:12

(Переписывая ответ от этот вопрос, так как он здесь актуален.)

При отладке, если вы просто хотите увидеть события, я рекомендую либо ...

  1. Визуальное событие
  2. Раздел Элементы инструментов разработчика Chrome: выберите элемент и найдите «Слушатели событий» в правом нижнем углу (аналогично Firefox).

Если вы хотите использовать события в своем коде и используете jQuery до версии 1.8, вы можете использовать:

$(selector).data("events")

получить события. Начиная с версии 1.8 использование .data ("событий") больше не поддерживается. (см. этот билет об ошибке). Ты можешь использовать:

$._data(element, "events")

Другой пример: записывать все события кликов по определенной ссылке в консоль:

var $myLink = $('a.myClass');
console.info($._data($myLink[0], "events").click);

(см. рабочий пример http://jsfiddle.net/HmsQC/)

К сожалению, с использованием данных $ ._ это не рекомендуется, за исключением отладки, поскольку это внутренняя структура jQuery и может измениться в будущих выпусках. К сожалению, я не знаю других простых способов доступа к событиям.

$._data(elem, "events") не работает с jQuery 1.10, по крайней мере, для событий, зарегистрированных с помощью $(elem).on('event', ...). Кто-нибудь знает, как их отлаживать?
Marius Gedminas 06.12.2013 15:19

Я не уверен, но я думаю, что первым параметром $._data может быть элемент, а не объект jQuery. Поэтому мне нужно исправить мой пример выше, чтобы он был console.info($._data($myLink[0], "events").click);.

Luke 07.12.2013 00:44

Прототип 1.7.1 способ

function get_element_registry(element) {
    var cache = Event.cache;
    if (element === window) return 0;
    if (typeof element._prototypeUID === 'undefined') {
        element._prototypeUID = Element.Storage.UID++;
    }
    var uid =  element._prototypeUID;           
    if (!cache[uid]) cache[uid] = {element: element};
    return cache[uid];
}

Chrome, Firefox, Vivaldi и Safari поддерживают getEventListeners(domElement) в своей консоли Developer Tools.

Это можно использовать для большинства целей отладки.

Ниже приведена очень хорошая рекомендация по его использованию: https://developers.google.com/web/tools/chrome-devtools/console/utilities#geteventlisteners

+1. Код, специфичный для браузера, для меня не проблема, потому что я пытаюсь получить некорректную работу страницы, которую не контролирую.

Grault 19.08.2013 09:54

приятно, но работает только в командной строке консоли Chrome :(

gillyspy 20.12.2013 20:25

В каких версиях Chrome это доступно, потому что 40 вроде бы его нет ...

jave.web 14.03.2015 03:23

@ jave.web Сейчас я использую 41.0.2272.89. Функция все еще существует.

Raghav 14.03.2015 07:08

@Raghav ах, спасибо, использование getEventListeners(object)НЕТ:obj getEventListeners(), как я сначала подумал :)

jave.web 15.03.2015 22:53

Вы могли бы сэкономить мне 3 часа, если бы объяснили, как получить исходный код слушателя событий. Эта «ссылка» ничего не объясняла. На случай, если кто-то еще проиграет, вот как это сделать: var list = getEventListeners(document.getElementById("YOURIDHERE")); console.info(list["focus"][0]["listener"].toString()). Измените «фокус» на событие, которое вы хотите проверить, и число, если у одного и того же события есть несколько слушателей.

doABarrelRoll721 20.02.2016 08:06

СОВЕТ: getEventListeners($0) получит прослушиватели событий для элемента, на котором вы сосредоточились в инструментах разработчика Chrome. Я использую это все время. Мне нравится не использовать функции querySelector или get__By_

cacoder 01.02.2017 02:46

@CliffordFajardo Похоже, это хорошая скрытая функция. <3

jeromej 03.07.2017 00:05

Как и Ориадам упомянул в своем комментарии, внутренние инструменты разработчика Chrome и Firefox (F12) имеют встроенную программу просмотра событий.

Franklin Yu 15.06.2018 02:01

Opera 12 (не последняя версия движка Chrome Webkit). Стрекоза имеет это некоторое время и, очевидно, отображается в структуре DOM. На мой взгляд, это превосходный отладчик, и это единственная оставшаяся причина, по которой я все еще использую версию на основе Opera 12 (нет версии v13, v14, а в версии v15 Webkit все еще отсутствует Dragonfly)

Используйте getEventListeners в Гугл Хром:

getEventListeners(document.getElementByID('btnlogin'));
getEventListeners($('#btnlogin'));

Uncaught ReferenceError: getEventListeners не определен

Bryan Grace 19.11.2015 01:43

getEventListeners работает только в консоли разработчика Chrome. И это дубликат этого более детального ответа: stackoverflow.com/a/16544813/1026

Nickolay 13.02.2016 16:20

1: Prototype.observe использует Element.addEventListener (см. исходный код)

2: Вы можете переопределить Element.addEventListener, чтобы запомнить добавленных слушателей (удобное свойство EventListenerList было удалено из предложения спецификации DOM3). Запустите этот код до того, как будет прикреплено какое-либо событие:

(function() {
  Element.prototype._addEventListener = Element.prototype.addEventListener;
  Element.prototype.addEventListener = function(a,b,c) {
    this._addEventListener(a,b,c);
    if (!this.eventListenerList) this.eventListenerList = {};
    if (!this.eventListenerList[a]) this.eventListenerList[a] = [];
    this.eventListenerList[a].push(b);
  };
})();

Читайте все события:

var clicks = someElement.eventListenerList.click;
if (clicks) clicks.forEach(function(f) {
  alert("I listen to this function: "+f.toString());
});

И не забудьте переопределить Element.removeEventListener, чтобы удалить событие из пользовательского Element.eventListenerList.

3: здесь свойство Element.onclick требует особого ухода:

if (someElement.onclick)
  alert("I also listen tho this: "+someElement.onclick.toString());

4: не забудьте атрибут содержимого Element.onclick: это две разные вещи:

someElement.onclick = someHandler; // IDL attribute
someElement.setAttribute("onclick","otherHandler(event)"); // content attribute

Так что вам тоже нужно с этим справиться:

var click = someElement.getAttribute("onclick");
if (click) alert("I even listen to this: "+click);

Букмарклет Visual Event (упомянутый в самом популярном ответе) только крадет кеш обработчика пользовательской библиотеки:

It turns out that there is no standard method provided by the W3C recommended DOM interface to find out what event listeners are attached to a particular element. While this may appear to be an oversight, there was a proposal to include a property called eventListenerList to the level 3 DOM specification, but was unfortunately been removed in later drafts. As such we are forced to looked at the individual Javascript libraries, which typically maintain a cache of attached events (so they can later be removed and perform other useful abstractions).

As such, in order for Visual Event to show events, it must be able to parse the event information out of a Javascript library.

Переопределение элемента может быть сомнительным (например, потому что есть некоторые специфические функции DOM, такие как живые коллекции, которые нельзя закодировать в JS), но он дает поддержку eventListenerList изначально и работает в Chrome, Firefox и Opera (не работает в IE7. ).

Инструменты разработчика Firefox теперь делают это. События отображаются при нажатии кнопки «ev» справа от дисплея каждого элемента, включая события jQuery и ДОМ.

Screenshot of Firefox developer tools' event listener button in the inspector tab

Я посмотрел на один из элементов dom на странице, на которой букмарклет Visual Event 2 показывает связанное с событием событие, и увидел маленькую кнопку «ev» справа, как вы показываете.

Eric 04.02.2015 00:07

Слушатель событий Firefox может обнаруживать события, делегированные jQuery, в то время как Chrome нужен плагин для этого.

Nick Tsai 04.08.2017 09:31

Я пытаюсь сделать это в jQuery 2.1, а с методом «$().click() -> $(element).data("events").click;» это не работает.

Я понял, что в моем случае работают только функции $ ._ data ():

	$(document).ready(function(){

		var node = $('body');
		
        // Bind 3 events to body click
		node.click(function(e) { alert('hello');  })
			.click(function(e) { alert('bye');  })
			.click(fun_1);

        // Inspect the events of body
		var events = $._data(node[0], "events").click;
		var ev1 = events[0].handler // -> function(e) { alert('hello')
		var ev2 = events[1].handler // -> function(e) { alert('bye')
		var ev3 = events[2].handler // -> function fun_1()
        
		$('body')
			.append('<p> Event1 = ' + eval(ev1).toString() + '</p>')
			.append('<p> Event2 = ' + eval(ev2).toString() + '</p>')
			.append('<p> Event3 = ' + eval(ev3).toString() + '</p>');        
	
	});

	function fun_1() {
		var txt = 'text del missatge';	 
		alert(txt);
	}
<script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>
</body>

Полностью рабочее решение на основе ответ Яна Турона - ведет себя как getEventListeners() из консоли:

(Есть небольшая ошибка с дубликатами. В любом случае, она не ломается.)

(function() {
  Element.prototype._addEventListener = Element.prototype.addEventListener;
  Element.prototype.addEventListener = function(a,b,c) {
    if (c==undefined)
      c=false;
    this._addEventListener(a,b,c);
    if (!this.eventListenerList)
      this.eventListenerList = {};
    if (!this.eventListenerList[a])
      this.eventListenerList[a] = [];
    //this.removeEventListener(a,b,c); // TODO - handle duplicates..
    this.eventListenerList[a].push({listener:b,useCapture:c});
  };

  Element.prototype.getEventListeners = function(a){
    if (!this.eventListenerList)
      this.eventListenerList = {};
    if (a==undefined)
      return this.eventListenerList;
    return this.eventListenerList[a];
  };
  Element.prototype.clearEventListeners = function(a){
    if (!this.eventListenerList)
      this.eventListenerList = {};
    if (a==undefined){
      for(var x in (this.getEventListeners())) this.clearEventListeners(x);
        return;
    }
    var el = this.getEventListeners(a);
    if (el==undefined)
      return;
    for(var i = el.length - 1; i >= 0; --i) {
      var ev = el[i];
      this.removeEventListener(a, ev.listener, ev.useCapture);
    }
  };

  Element.prototype._removeEventListener = Element.prototype.removeEventListener;
  Element.prototype.removeEventListener = function(a,b,c) {
    if (c==undefined)
      c=false;
    this._removeEventListener(a,b,c);
      if (!this.eventListenerList)
        this.eventListenerList = {};
      if (!this.eventListenerList[a])
        this.eventListenerList[a] = [];

      // Find the event in the list
      for(var i=0;i<this.eventListenerList[a].length;i++){
          if (this.eventListenerList[a][i].listener==b, this.eventListenerList[a][i].useCapture==c){ // Hmm..
              this.eventListenerList[a].splice(i, 1);
              break;
          }
      }
    if (this.eventListenerList[a].length==0)
      delete this.eventListenerList[a];
  };
})();

Применение:

someElement.getEventListeners([name]) - вернуть список слушателей событий, если задано имя, вернуть массив слушателей для этого события

someElement.clearEventListeners([name]) - удалить всех слушателей событий, если задано имя, удалить слушателей только для этого события

Это хороший ответ, но я не могу заставить его работать с элементами body и document.

David Bradshaw 24.08.2015 22:55

Действительно хорошее решение!

Dzhakhar Ukhaev 21.01.2017 13:56

@ Питер Мортенсен, почему ты сменил имя Яна? :)

n00b 29.01.2017 15:11

@ Дэвид Брэдшоу: потому что тело, документ и окно имеют свой собственный прототип, а не прототип элемента ...

Stefan Steiger 21.07.2018 18:04

@ n00b: есть ошибка. Вот почему хммм. Вы используете оператор-запятую в операторе if для слушателя и useCaption ... Оператор-запятая оценивает каждый из своих операндов (слева направо) и возвращает значение последнего операнда. Итак, вы удаляете первый eventListener, который соответствует useCapture, независимо от типа события ... Это должно быть && вместо запятой.

Stefan Steiger 23.07.2018 03:01

Вы можете обернуть собственные методы DOM для управления слушателями событий, поместив это в верхнюю часть вашего <head>:

<script>
    (function(w){
        var originalAdd = w.addEventListener;
        w.addEventListener = function(){
            // add your own stuff here to debug
            return originalAdd.apply(this, arguments);
        };

        var originalRemove = w.removeEventListener;
        w.removeEventListener = function(){
            // add your own stuff here to debug
            return originalRemove.apply(this, arguments);
        };
    })(window);
</script>

H / T @ les2

Пожалуйста, поправьте меня, если я ошибаюсь, но разве это не только для прослушивателей событий, прикрепленных к окну?

Maciej Krawczyk 03.02.2017 20:25

@MaciejKrawczyk да, и те, что пузырились

Jon z 06.02.2017 19:47

Есть симпатичный Расширение jQuery Events:

(тема источник)

Недавно я работал с событиями и хотел просматривать / контролировать все события на странице. Посмотрев на возможные решения, я решил пойти своим путем и создать собственную систему мониторинга событий. Итак, я сделал три вещи.

Во-первых, мне нужен был контейнер для всех слушателей событий на странице: это объект EventListeners. У него есть три полезных метода: add(), remove() и get().

Затем я создал объект EventListener для хранения необходимой информации для события, а именно: target, type, callback, options, useCapture, wantsUntrusted, и добавил метод remove() для удаления слушателя.

Наконец, я расширил собственные методы addEventListener() и removeEventListener(), чтобы они работали с объектами, которые я создал (EventListener и EventListeners).

Применение:

var bodyClickEvent = document.body.addEventListener("click", function () {
    console.info("body click");
});

// bodyClickEvent.remove();

addEventListener() создает объект EventListener, добавляет его в EventListeners и возвращает объект EventListener, чтобы его можно было удалить позже.

EventListeners.get() можно использовать для просмотра слушателей на странице. Он принимает EventTarget или строку (тип события).

// EventListeners.get(document.body);
// EventListeners.get("click");

Демо

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

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @include      https://stackoverflow.com/*
// @grant        none
// ==/UserScript==

(function() {
    fetch("https://raw.githubusercontent.com/akinuri/js-lib/master/EventListener.js")
        .then(function (response) {
            return response.text();
        })
        .then(function (text) {
            eval(text);
            window.EventListeners = EventListeners;
        });
})(window);

И когда мы перечисляем всех слушателей, там говорится, что есть 299 слушателей событий. «Кажется» есть какие-то дубликаты, но я не знаю, действительно ли они дублируются. Не все типы событий дублируются, поэтому все эти «дубликаты» могут быть отдельным слушателем.

screenshot of console listing all event listeners in this page

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


Обновлять: Похоже, это не работает с jQuery. Когда я просматриваю EventListener, я вижу, что обратный вызов

function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}

Я считаю, что это относится к jQuery, а не к обратному вызову. jQuery сохраняет фактический обратный вызов в свойствах EventTarget:

$(document.body).click(function () {
    console.info("jquery click");
});

Чтобы удалить прослушиватель событий, необходимо передать обратный вызов методу removeEventListener(). Поэтому для того, чтобы эта функция работала с jQuery, требуется дальнейшая модификация. Я могу исправить это в будущем.

изменение этих функций позволит вам регистрировать добавленных слушателей:

EventTarget.prototype.addEventListener
EventTarget.prototype.attachEvent
EventTarget.prototype.removeEventListener
EventTarget.prototype.detachEvent

прочтите остальных слушателей с

console.info(someElement.onclick);
console.info(someElement.getAttribute("onclick"));

Чтобы все прослушиватели событий на странице распечатывались вместе с их элементами

Array.from(document.querySelectorAll("*")).forEach(e => {
    const ev = getEventListeners(e)
    if (Object.keys(ev).length !== 0) console.info(e, ev)
})

Другие вопросы по теме