В статье приводится сравнение способов добавления обработчиков через on(click), addEventListener и attachEvent.
Рассмотрены особенности, плюсы и минусы разных способов.
Считается, что вы знакомы с основными свойствами объекта события и порядком их обработки.
Самый универсальный метод. У него есть, пожалуй, только один существенный недостаток: можно повесить лишь один обработчик.
Кроме того, есть глюк с iframe: в Firefox не будет работать обработчик, назначенный так:
iframeElement.onclick = function(event) { .... }
Но будет прекрасно работать addEventListener:
iframeElement.addEventListener( "click", ... )
Методы attachEvent/addEventListener имеют ряд общих недостатков.
Во-первых, ни W3C ни Microsoft не определяют порядок срабатывания обработчиков. Несколько обработчиков одного события на элементе могут сработать в любом порядке.
На текущий момент (март 2010) addEventListener сохраняет порядок назначения обработчиков, а attachEvent в IE - нет.
elem.attachEvent("onclick", handler);
elem.attachEvent("onclick", handler2);
// может быть так, что handler2 сработает раньше handler.
// так, судя по демке ниже, ведет себя IE.
// а может быть, handler сработает раньше handler2.
// так в демо ниже ведет себя Opera
// ... вообще, порядок неопределен
На одну и ту же кнопку вешаются пять обработчиков onclick: первый выдает "1", второй выдает "2" и т.п.
Есть еще одна проблема, с которой можно столкнуться при управлении событиями: нельзя точно сказать установлен ли определённый обработчик, или нет, и какие обработчики установлены на данный момент.
В спецификации DOM 3 существует объект eventListenerList, но он слишком новый и на данный момент не поддерживается ни одним из браузеров.
attachEventОбработчик ставится как:
element.attachEvent( "on"+имя_события, обработчик)
Основной недостаток attachEvent заключается в том, что функция-обработчик не получает текущий элемент, на котором сработало событие, ни в каком виде.
Значение this указывает на window, а свойство event.currentTarget отсутствует.
И это достаточно важная особенность!
Например, пусть мы хотим подсвечивать divElem при клике.
divElem с разным текстом и различными ссылками, и даже с жирным текстом внутри тага <b>
Конечно, же мы повесим обработчик на divElem:
divElem.attachEvent("onclick", handler)
Но при клике из объекта события event в IE можно получить только srcElement, то есть самый глубокий кликнутый элемент. Он может быть ссылкой <a> или элементом <b>, но нам-то нужны не они, а сам divElem, чтобы его подсветить.
Обработчик, добавленный при помощи attachEvent никак не может выяснить объект, на который подвешен.
Впрочем, это легко обойти при помощи небольшого замыкания, корректно передающего указатель this:
divElem.attachEvent("onclick", function() { handler.call(divElem) })
Но этот код порождает утечку памяти в Internet Explorer 6, на который не установлено исправляющее обновление, вышедшее в июне 2007 года, из-за круговой ссылки DOM <-> JS.
addEventListenerРешение W3C работает во всех современных браузерах, кроме Internet Explorer.
Установка обработчика:
element.addEventListener( имя_события, обработчик, фаза)
Пожалуй, особенных недостатков, кроме общих с attachEvent, у этого способа нет.
В следующей статье разобран способ, позволяющий добавлять обработчики кроссбраузерно и свободный от описанных недостатков.