Пишем качественный код на jQuery

шапка

На данный момент существует достаточное количество статей, в которых обсуждается производительность библиотеки jQuery и JavaScript. Однако в этой статье я хотел бы подвести черту и собрать воедино основной набор советов по улучшению производительности и качества кода, который вы пишете, а также поделиться несколькими ценными наблюдениями из моего собственного опыта. Качественный код – это прежде всего быстрые приложения и сайты без лишнего мусора. В конце концов, быстрая отрисовка страниц и улучшенное реагирование принесут вашим пользователям более позитивный опыт взаимодействия.

Важно помнить несколько ключевых моментов. Во-первых, jQuery — это и есть JavaScript. Что, в свою очередь, значит, что нам нужно использовать одни и те же общие правила при написании кода, гайдлайны стиля и передовые практики, как для самого языка, так и для работы с библиотекой, на котором она написана.

Во-вторых, я настойчиво рекомендую всем новичкам, которые только начали осваиваться с JavaScript, перед тем, как связываться с jQuery, прочитать следующие статьи: о передовых JavaScript-практиках для начинающих, и о том, как писать качественный JavaScript-код.

Когда вы будете готовы использовать jQuery, я настоятельно советую вам придерживаться нижеследующих принципов:

Кэшируйте выборку в переменных

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

// плохо
h = $('#element').height();
$('#element').css('height',h-20);

// хорошо
$element = $('#element');
h = $element.height();
$element.css('height',h-20);

Не используйте глобальные переменные

Для jQuery, как и для JavaScript, лучше всего делать так, чтобы переменные были замкнуты внутри функций, в которых они используются.

// плохо
$element = $('#element');
h = $element.height();
$element.css('height',h-20);

// хорошо
var $element = $('#element');
var h = $element.height();
$element.css('height',h-20);

Используйте венгерскую нотацию

Если говорить простыми словами, венгерская нотация1 в jQuery — это когда в начале переменной стоит символ доллара, и вам легко сразу понять, что эта переменная содержит jQuery-объект.

// плохо
var first = $('#first');
var second = $('#second');
var value = $first.val();

// хорошо - перед объектами, которые управляются jQuery, мы ставим символ $
var $first = $('#first');
var $second = $('#second'),
var value = $first.val();

Используйте цепочки переменных (паттерн одного ‘var’)

Вместо того чтобы писать директиву var для каждой объявляемой переменной, можно объединить несколько переменных в одну var-цепочку. Я советую ставить все переменные, не имеющие на текущий момент конкретного значения, в конец цепочки.

var
  $first = $('#first'),
  $second = $('#second'),
  value = $first.val(),
  k = 3,
  cookiestring = 'SOMECOOKIESPLEASE',
  i,
  j,
  myArray = {};

Используйте ‘On’

Последние версии библиотеки jQuery привнесли изменения в функции типа click() — теперь это сокращение от on('click'). В более ранних версиях click() являлся сокращением от bind(). Начиная с версии jQuery 1.7 предпочтительный метод для привязки обработчиков событий — on(). Для единообразия гораздо проще использовать on() везде в подобных случаях.

// плохо
$first.click(function(){
	$first.css('border','1px solid red');
	$first.css('color','blue');
});

$first.hover(function(){
	$first.css('border','1px solid red');
})

// лучше
$first.on('click',function(){
	$first.css('border','1px solid red');
	$first.css('color','blue');
})

$first.on('hover',function(){
	$first.css('border','1px solid red');
})

Концентрированный JavaScript

В общем, там, где есть для этого возможность, лучше совмещать несколько функций в одну.

// плохо
$first.click(function(){
	$first.css('border','1px solid red');
	$first.css('color','blue');
});

// лучше
$first.on('click',function(){
	$first.css({
		'border':'1px solid red',
		'color':'blue'
	});
});

Используйте цепочки

Библиотека jQuery позволяет вам очень просто связывать методы в цепочки. Пользуйтесь этим!

// плохо
$second.html(value);
$second.on('click',function(){
	alert('hello everybody');
});
$second.fadeIn('slow');
$second.animate({height:'120px'},500);

// лучше
$second.html(value);
$second.on('click',function(){
	alert('hello everybody');
}).fadeIn('slow').animate({height:'120px'},500);

Оставляйте код читаемым

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

// плохо
$second.html(value);
$second.on('click',function(){
	alert('всем привет');
}).fadeIn('slow').animate({height:'120px'},500);

// лучше
$second.html(value);
$second
	.on('click',function(){ alert('всем привет');})
	.fadeIn('slow')
	.animate({height:'120px'},500);

Используйте сокращенные вычисления для логических выражений

Сокращенное вычисление означает, что выражения оцениваются слева направо с использованием операторов && (логическое и) и || (логическое или).

// плохо
function initVar($myVar) {
	if(!$myVar) {
		$myVar = $('#selector');
	}
}

// лучше
function initVar($myVar) {
	$myVar = $myVar || $('#selector');
}

Сокращайте!

Один из способов сделать код более компактным — воспользоваться сокращениями.

// плохо
if(collection.length > 0){..}

// лучше
if(collection.length){..}

Отделяйте элементы, когда нужно провести с ними ресурсоёмкие операции

Если вы собираетесь провести ряд ресурсоёмких операций над элементом DOM, рекомендуется отделить его от документа, а потом добавить снова.

// плохо
var
	$container = $("#container"),
	$containerLi = $("#container li"),
	$element = null;

$element = $containerLi.first();
//... много сложных манипуляций

// лучше
var
	$container = $("#container"),
	$containerLi = $container.find("li"),
	$element = null;

$element = $containerLi.first().detach();
//... много сложных манипуляций

$container.append($element);

Знайте особенности

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

// плохо
$('#id').data(key,value);

// лучше (быстрее)
$.data('#id',key,value);

Кэшируйте родительские элементы для подзапросов

Как я говорил выше, поиск по DOM — дорогостоящая в плане ресурсов операция. Зачастую лучше кэшировать родительские элементы, а потом использовать уже закэшированные элементы для выбора дочерних.

// плохо
var
	$container = $('#container'),
	$containerLi = $('#container li'),
	$containerLiSpan = $('#container li span');

// лучше (и быстрее)
var
	$container = $('#container '),
	$containerLi = $container.find('li'),
	$containerLiSpan= $containerLi.find('span');

Не используйте универсальный селектор

Универсальный селектор в совокупности с другими селекторами — это очень медленная выборка.

// плохо
$('.container > *');

// лучше
$('.container').children();

Вместо подразумеваемого универсального селектора, пишите конкретные селекторы

Если вы не указываете никакого селектора, по умолчанию подставляется универсальный селектор (*).

// плохо
$('.someclass :radio');

// лучше
$('.someclass input:radio');

Оптимизируйте селекторы

Например, если вы используете id — это уже достаточно специфический запрос, поэтому не нужно добавлять дополнительную специфичность в выборку через добавление других селекторов.

// плохо
$('div#myid');
$('div#footer a.myLink');

// лучше
$('#myid');
$('#footer .myLink');

Не используйте в запросе путь из нескольких id

Еще раз повторюсь, если вы используете id правильно, то одного id вполне достаточно, и дополнительная специфичность в запросе из нескольких вложенных id селекторов не требуется.

// плохо
$('#outer #inner');

// лучше
$('#inner');

Старайтесь использовать последнюю версию библиотеки

Чаще всего новая версия является лучшей по сравнению с предыдущей. Обычно она легче или, например, быстрее. Однако не стоит забывать об обратной совместимости и поддержки кода. Например, версия библиотеки jQuery 2.0 не поддерживает версии браузера Internet Explorer 6, 7 и 8.

Не используйте устаревшие методы

Всегда смотрите на список устаревших методов в каждой новой версии и старайтесь их не использовать в вашем коде.

// плохо - метод live является устаревшим
$('#stuff').live('click', function() {
  console.log('ура!');
});

// лучше
$('#stuff').on('click', function() {
  console.log('ура!');
});

Загружайте jQuery с CDN

Наиболее быстрый способ передать пользователю скрипт с ближайшего к нему сервера — использовать технологию CDN от Google. Чтобы использовать CDN Google, используйте в коде следующий адрес: http://code.jquery.com/jquery-latest.min.js

Старайтесь совмещать jQuery и нативный JavaScript

Как я говорил выше, jQuery — это не что иное, как JavaScript, а, значит, на jQuery мы всего лишь делаем те же самые вещи, которые могли бы делать и на встроенном в браузер JavaScript. Конечно же, когда вы пишете на нативном («ванильном») JavaScript, это зачастую приводит к длинным файлам с нечитаемым кодом, который сложно поддерживать. Однако, это также означает и то, что ваш код будет исполняться быстрее. Помните, что нет такого js-фреймворка, который был бы легче в исполнении для браузера, чем операции на нативном JavaScript.

jq

(Кликните на картинку и проверьте)

Из-за разницы в производительности между встроенным в браузер JavaScript и jQuery я настоятельно рекомендую использовать их вместе (но делать это со всей ответственностью). И, по возможности, используйте как можно чаще нативные аналоги для функций jQuery.

Напутствие напоследок

Напоследок, я рекомендую вам прочитать эту статью об увеличении производительности jQuery. В ней так же содержится ряд других замечательных советов по оптимизации кода, которые, несомненно, будут вам интересны, если вы хотите поглубже разобраться в этой теме.

Не забывайте также, что использование jQuery – это выбор, а не требование. Подумайте, зачем вы вообще используете jQuery. Для преобразований DOM? AJAX? Шаблонов? CSS-анимаций? Как движок селекторов? Возможно, для ваших задач имеет смысл использовать микрофреймворки на JavaScript или какую нибудь кастомную сборку jQuery, которая будет четко отвечать требованиям вашего проекта.


Примечания

1.Венге́рская нота́ция в программировании — соглашение об именовании переменных, констант и прочих идентификаторов в коде программ. Своё название венгерская нотация получила благодаря программисту компании Microsoft венгерского происхождения Чарльзу Симони, предложившему её ещё во времена разработки первых версий MS-DOS. Эта система стала внутренним стандартом Майкрософт. Подробнее о ней вы можете прочесть в Википедии.