Тестирование производительности селекторов jQuery

Всем известно что jQuery может все. Но далеко не всем известно что jQuery это может несколькими способами. Вот именно об этом я и хочу сегодня поговорить, а заодно проверить какой способ быстрее. Подвергну тестам вышедшую сегодня в свет jQuery 1.3.2, вставленную в страницу результатов Google, общий вес html файла чуть более чем 25кб, все возможные тэги в наличии. Еще хотелось бы акцентировать внимание на том что я не буду использовать псевдо-селектор :not() , так как смысловой нагрузки он не несет, хотя дает еще один способ выбрать элемент.

Первым я протестирую контекст, проверять буду вот таким скриптом


var start = new Date();
for(var i=0;i<1000;i++)
	$....
var stop = new Date();
console.log(stop-start)

Я не будем добавлять ничего нового к коду Google, а только попробуем собрать коллекцию li.

$(«li», document) 120
$(«li», «ol») 220

Вывод из первого эксперимента — сам по себе контекст это еще один поиск по DOM дереву, поэтому задавать контекст стоит только если второй запрос ограничит первый на столько что сэкономленное время будет больше чем время второго запроса, такого эффекта можно добиться например указав id родителя (не обязательного прямого) в контексте.

Второй пример покажет как лучше всего получить всех прямых потомков.

$(«ol>*») 1800+
$(«ol>li») 215
$(«ol»).children(«li») 330

Не используйте звездочку — это не оправдано в 99.9% случаев (а в этом примере * возвращает еще и затесавшийся случайно элемент link) и не стоит без особой надобности использовать метод children — он тормозит.

В третьем примере я протестирую получение первого прямого потомка.

$(«ol>li:first») 375
$(«ol>li:eq(0)») 380
$(«ol>li»).eq(0) 240
$(«ol:first-child») 140
$(«ol:nth-child(1)») 165
$(«ol»).children(«li») 330
$(«ol»).find(«:first-child») 1500+
$(«ol»).find(«:nth-child(1)») 2600+

Не могу найти разумного объяснения почему так тормозит find, но наверное на это есть какие-то причины. А еще интересна разница в использовании eq(0) как селектора и как метода — дольше в полтора раза.

Думаю стоит отвлечся от потомков и протестировать атрибуты. Вытащим input у которых type=radio

$(«:radio») 1500+
$(«[type=radio]») 2400+
$(«input:radio») 200
$(«input[type=radio]») 240
$(«input»).filter(«[type=radio]») 320

Похоже фильтром тоже не стоит злоупотреблять, а псевдо-селекторы придуманы не только для удобства в написании

Ну и конечно надо доколупаться до классов а то было бы не честно

$(«[class^=gac]») 2700+
$(«.gac_a, .gac_c, .gac_d, .gac_e, .gac_m») 1200+
$(«.gac_a»).add(«.gac_c»).add(«.gac_d»).add(«.gac_e»).add(«.gac_m») 1100+

Магия…