На этом шаге мы рассмотрим дальнейшую оптимизацию примера.
Оптимизация программного кода, которую мы только что провели, является примером рефакторинга - модификации существующего программного кода для выполнения той же задачи более эффективным и элегантным способом. С целью изучения других возможностей рефакторинга рассмотрим детальнее обработчики событий, присоединяемые к каждой из кнопок. Аргумент метода .removeClass() является необязательным; если он отсутствует, метод удалит из элемента все классы. Мы можем упростить наш программный код, воспользовавшись этой особенностью, как показано ниже:
$(document).ready(function() { $('#switcher-default').bind('click', function() { $('body').removeClass(); }); $('#switcher-narrow').bind('click', function() { $('body').removeClass().addClass('narrow'); }); $('#switcher-large').bind('click', function() { $('body').removeClass().addClass('large'); }); $('#switcher .button').bind('click', function() { $('#switcher .button').removeClass('selected'); $(this).addClass('selected'); }); });
Обратите внимание, как изменился порядок выполнения операций из-за того, что мы выполняем удаление всех классов: метод .removeClass() должен вызываться первым, чтобы не отменить действие метода .addClass(), вызываемого в той же цепочке.
Теперь в обработчиках событий для всех кнопок используется один и тот же программный код. Его легко можно превратить в универсальный обработчик события click:
$(document).ready(function() { $('#switcher .button').bind('click', function() { $('body').removeClass(); $('#switcher .button').removeClass('selected'); $(this).addClass('selected'); }); $('#switcher-narrow').bind('click', function() { $('body').addClass('narrow'); }); $('#switcher-large').bind('click', function() { $('body').addClass('large'); }); });
Обратите внимание, что нам пришлось переместить универсальный обработчик выше специализированных. Метод .removeClass() должен вызываться раньше метода .addClass(), и мы можем учесть это обстоятельство благодаря тому, что библиотека jQuery всегда вызывает обработчики в порядке их регистрации.
Наконец, мы можем полностью избавиться от специализированных обработчиков, снова воспользовавшись контекстом обработчика события. Так как ключевое слово this содержит ссылку на элемент DOM, а не на объект jQuery, мы можем применить встроенные свойства DOM для определения идентификатора элемента, на котором был произведен щелчок. Благодаря этому мы можем присоединить один и тот же обработчик ко всем кнопкам и выполнять внутри него действия, различные для всех кнопок:
$(document).ready(function() { $('#switcher .button').bind('click', function() { $('body').removeClass(); if (this.id == 'switcher-narrow') { $('body').addClass('narrow'); } else if (this.id == 'switcher-large') { $('body').addClass('large'); } $('#switcher .button').removeClass('selected'); $(this).addClass('selected'); }); });
На следующем шаге мы рассмотрим сокращенную форму подключения обработчиков.