Мы привыкли писать код исходя из наших устоев - чтения слева-направо. В тоже время, многие JavaScript фрэймворки, такие как jQuery, YUI 3, NWMatcher, а так же нативный querySelectorAll, производят парсинг справа-налево.
Пример
Возьмём вот такой вот селектор:
$('.box p');
jQuery работает в обратном направлении. Всё начинается с поиска всех параграфов в DOM, а после идёт отбор только тех, у которых есть класс .box.
JSPerf
Используем сайт JsPerf.com для тестирования.
<div id="box">
<p> Hello </p>
</div>
// Тест
//1 .
$('#box p');
// 2.
$('#box').find('p');
Приведённый выше пример показывает, что использование find() или children() на 20-30% быстрее, в зависимости от браузера. Библиотека jQuery специальна оптимизирована для нахождения элемента, если в селекторе присутствует знак # ( $('#box') ). В этом случае jQuery не нужно использовать Sizzle (библиотека селекторов); Она сразу использует getElementById.
В этом случае $('#box p'), jQuery необходимо парсить строку при помощи Sizzle API, что займёт немного времени. Вот почему быстрее использовать $('.elems').first() чем $('.elems:first'), для выбора первого элемента.
Другой пример
Рассмотрим другой пример:
$('#container > :disabled');
Принцип работы селектора не очень сложен. Найти все выключенные элементы, которые находятся в контейнере #container. Однако, учитывая то, что мы узнали выше, jQuery и querySelectorAll работает справа-налево. Это означает, что jQuery выберет все элементы DOM, потом определит у каких из них стоит атрибут disabled. Таким образом jQuery пройдётся по всем элементам страницы.
// Где-то в недрах jQuery
disabled: function( elem ) {
return elem.disabled === true;
}
Как только собрана коллекция элементов, далее их проверяют по цепочке на наличие родителя с id #container. Можем сделать вывод, что это не очень эффективный подход. Поэтому нам нужно делать наши селекторы как можно менее массивными.
Мы можем исправить ситуацию следующим образом:
// Так будет быстрее
$('#container > input:disabled');
Этот код уменьшает поиск только до элементов input (не все элементы). Но тут мы так же можем использовать методы find или children. Так будет ещё быстрее:
$('#container').children('input:disabled');
Сильно уж не парьтесь
Я думаю, что полезно знать все эти техники, но сильно уж заморачиваться не стоит. Лучше концентрировать больше внимания на организацию кода и его структуру.
Тем не менее, всегда полезно знать, что происходит за кулисами - по крайней мере на самом низком уровне.