На этом шаге мы рассмотрим дальнейшую оптимизацию примера.
Оптимизация программного кода, которую мы только что провели, является примером рефакторинга - модификации существующего программного кода для выполнения той же задачи более эффективным и элегантным способом. С целью изучения других возможностей рефакторинга рассмотрим детальнее обработчики событий, присоединяемые к каждой из кнопок. Аргумент метода .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');
});
});
На следующем шаге мы рассмотрим сокращенную форму подключения обработчиков.