Как уже говорилось в пункте 8.8.4.2, Internet Explorer (вплоть до версии 6) стра_ дает утечками памяти, связанными с тем, что в качестве обработчиков событий используются вложенные функции. Рассмотрим следующий фрагмент:
// Добавить обработчик, проверяющий правильность заполнения формы
Когда вызывается эта функция, она добавляет обработчик события в заданный элемент формы. Обработчик события определен как вложенная функция, и хотя сама функция не ссылается ни на один из элементов формы, ссылки на них ока_ зываются захваченными в ее области видимости, как часть замыкания. В ре_ зультате элемент формы ссылается на JavaScript_объект Function, а объект (че_ рез цепочку области видимости) – обратно, на элемент формы. Такого рода цик_ лические ссылки могут вызывать в IE утечки памяти.
Одно из решений этой проблемы заключается в том, чтобы старательно избегать вложенных функций при программировании для IE. Другое решение – тщатель_ но удалить все обработчики событий в ответ на событие onunload(). В примере, который приводится в следующем разделе, используется второй вариант.
Пример: модель обработки событий, совместимая с IE
В этом разделе основное внимание уделяется ряду несовместимостей между мо_ делями обработки событий в IE и в DOM Level 2. В примере 17.2 представлен мо_ дуль, который преодолевает многие из этих несовместимостей. В модуле опреде_ лены две функции, Handler.add() и Handler.remove(), которые добавляют и удаля_ ют обработчики событий для заданного элемента. На платформах, поддерживаю_ щих метод addEventListener(), эти функции являются тривиальными обертками вокруг стандартных методов. Однако в IE 5 и более поздних версиях эти методы определены так, что преодолевают следующие несовместимости:
• Обработчики событий вызываются как методы зарегистрировавшего их эле_ мента.
• Обработчикам событий для расширения возможностей передается смодели_ рованный объект события, соответствующий стандарту DOM.
• Повторные попытки регистрации обработчиков событий игнорируются.
• С целью предотвращения утечек памяти в IE при выгрузке документа отме_ няется регистрация всех обработчиков событий.
Чтобы обработчики событий вызывались с корректным значением ключевого слова this, а также для того, чтобы передавать им смоделированный объект со_ бытия, в примере 17.2 функции_обработчики должны быть обернуты в другие функции, корректно вызывающие обработчиков. Самая интересная часть в этом примере – это программный код, который отображает функцию_обработчик, пе_ редаваемую методу Handler.add(), на функцию_обертку, фактически регистри_ руемую методом attachEvent(). Такого рода отображение должно выполняться
17.3. Модель обработки событий Internet Explorer
так, чтобы метод Handler.remove() мог удалить правильную функцию_обертку при удалении обработчиков в ходе выгрузки документа.
Пример 17.2. Код обеспечения совместимости с моделью события IE
/*
* Handler.js __ Переносимые функции регистрации и отмены регистрации
*
* Этот модуль определяет функции регистрации и отмены регистрации
* обработчиков событий Handler.add() и Handler.remove(). Обе функции
* принимают три аргумента:
*
* element: DOM_элемент, документ или окно, куда добавляется
* или откуда удаляется обработчик события.
*
* eventType: строка, определяющая тип события, для обработки которого
* вызывается обработчик. Используются имена типов в соответствии
* со стандартом DOM, в которых отсутствует префикс "on".
* Примеры: "click", "load", "mouseover".
*
* handler: Функция, которая вызывается при возникновении указанного
* события в заданном элементе. Данная функция вызывается как метод
* элемента, в котором она зарегистрирована, и ключевое слово "this"
* будет ссылаться на этот элемент. Функции_обработчику в качестве
* аргумента передается объект события. Данный объект будет либо
* стандартным объектом Event, либо смоделированным объектом.
* В случае передачи смоделированного объекта он будет обладать
* следующими свойствами, совместимыми со стандартом DOM: type, target,