Я ищу способ улучшить производительность селектора при вызове jQuery. Конкретно такие вещи:
$("div.myclass") быстрее, чем $(".myclass")
Я бы подумал, что это возможно, но я не знаю, достаточно ли умен jQuery, чтобы ограничить поиск по имени тега и т. д. У кого-нибудь есть идеи, как сформулировать строку селектора jQuery для лучшей производительности?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я был в некоторых списках рассылки jQuery, и, судя по тому, что я там читал, они, скорее всего, фильтруют по имени тега, а затем по имени класса (или наоборот, если это было быстрее). Они одержимы скоростью и готовы на все, чтобы получить хоть каплю производительности.
В любом случае я бы не стал особо беспокоиться об этом, если вы не запускаете этот селектор тысячи раз в секунду.
Если вы действительно обеспокоены, попробуйте провести сравнительный анализ и посмотреть, что быстрее.
Несомненно, что фильтрация по имени тега выполняется намного быстрее, чем фильтрация по имени класса.
Так будет до тех пор, пока все браузеры не реализуют изначально getElementsByClassName, как в случае с getElementsByTagName.
Я обновил Компонентхаус.com/article-19 из ответа Джеффа, чтобы использовать последнюю версию jQuery, похоже, что из второго теста A и B имеют одинаковую производительность в Opera 10 и firefox 3.5. Я не мог заставить его работать в IE8 (хотя я и не пробовал много). Так что, похоже, я ошибся в своем предыдущем комментарии.
@hoffmann, наверное, нет. Если мы предположим, что обе эти функции реализованы с помощью b-деревьев, я не понимаю, почему getElementsByClassName будет работать медленнее ... Вам все равно придется создать индекс, прежде чем вы сможете использовать эту функцию ...
@AlienWebguy: Смысл этого ответа в том, что некоторые браузеры не поддерживают getElementsByClassName, а это означает, что элемент каждый на странице необходимо протестировать для класса. Имейте в виду, что этот ответ был дан и в 2008 году. ; о)
т.е. <= 8 не в счет - весь интернет отстой для этих людей;)
@AlienWebguy: ваш тест неточно представляет большую страницу с множеством элементов DOM. Ваш тест выполняется быстрее благодаря более простому набору фильтров, а не более быстрому поиску.
Я добавлю замечание, что в 99% веб-приложений, даже тяжелых приложений ajax, скорость соединения и отклик веб-сервера будут влиять на производительность вашего приложения, а не javascript. Я не говорю, что вы должны писать намеренно медленный код или что в целом осознавать, какие вещи могут быть быстрее других, нехорошо.
Но мне интересно, пытаетесь ли вы решить проблему, которая на самом деле еще не существует, или даже если вы оптимизируете что-то, что может изменять в ближайшем будущем (скажем, если больше людей начнут использовать браузер, поддерживающий getElementsByClassName() упомянутую ранее функцию), в результате чего ваш оптимизированный код действительно работает медленнее.
Рассмотрите возможность использования библиотеки Оливера Стила Sequential для вызова методов с течением времени, а не всех сразу.
http://osteele.com/sources/javascript/sequential/
Метод «в конечном итоге» помогает вызвать метод через определенный период времени с момента его первоначального вызова. Метод «последовательно» позволяет ставить в очередь несколько задач в течение определенного периода времени.
Очень полезно!
Еще одно место для поиска информации о производительности - это страница анализа селекторов Хуго Видаля Тейшейры.
http://www.componenthouse.com/article-19
Это дает хорошее снижение скорости для селектора по идентификатору, селектора по классу и имени тега префикса селектора.
Самыми быстрыми селекторами по идентификатору были: $ ("# id")
Самый быстрый селектор по классам: $ ('tag.class')
Так что префикс по тегу помогал только при выборе по классу!
В некоторых случаях вы можете ускорить запрос, ограничив его контекст. Если у вас есть ссылка на элемент, вы можете передать ее в качестве второго аргумента, чтобы ограничить объем запроса:
$(".myclass", a_DOM_element);
должно быть быстрее, чем
$(".myclass");
если у вас уже есть a_DOM_element, и он значительно меньше всего документа.
Насколько я помню, для $('.myclass', a_DOM_element) jQuery преобразуется в / вызывает $(a_DOM_element).find('.myclass'), поэтому мог бы будет немного быстрее, если просто использовать find(), а не устанавливать контекст селектора, как в вашем первом примере.
Вот как повысить производительность ваших селекторов jQuery:
$('.select', this))Чтобы полностью понять, что быстрее, вы должны понимать, как работает синтаксический анализатор CSS.
Селектор, который вы передаете, разделяется на узнаваемые части с помощью RegExp, а затем обрабатывается по частям.
Некоторые селекторы, такие как ID и TagName, используют встроенную реализацию браузера, которая работает быстрее. В то время как другие, такие как класс и атрибуты, программируются отдельно и, следовательно, намного медленнее, требуя цикла по выбранным элементам и проверки каждого имени класса.
Так что да, чтобы ответить на ваш вопрос:
$ ('tag.class') быстрее, чем просто $ ('. class'). Почему? В первом случае jQuery использует собственную реализацию браузера, чтобы отфильтровать выбор только до тех элементов, которые вам нужны. Только тогда он запускает более медленную реализацию .class, фильтрующую то, что вы просили.
Во втором случае jQuery использует свой метод для фильтрации каждого элемента путем захвата класса.
Это распространяется дальше, чем jQuery, поскольку все библиотеки javascript основаны на нем. Единственный другой вариант - использовать xPath, но в настоящее время он не очень хорошо поддерживается всеми браузерами.
отличный совет из заданного мною вопроса: используйте стандартные селекторы CSS везде, где это возможно. Это позволяет jQuery использовать Селекторы API. Согласно тесты, выполненные Джоном Ресигом, это приводит к почти нативной производительности для селекторов. Следует избегать таких функций, как :has() и :contains().
Из моих исследований поддержка Selectors API была представлена в jQuery 1.2.7, Firefox 3.1, IE 8, Opera 10, Safari 3.1.
Если я не ошибаюсь, jQuery также является движком снизу вверх. Это означает, что $('#foo bar div') намного медленнее, чем $('bar div #foo'). Например, $('#foo a') просматривает все элементы a на странице и проверяет, есть ли у них предок #foo, что делает этот селектор чрезвычайно неэффективным.
Возможно, Ресиг уже оптимизировал для этого сценария (меня не удивит, если он это сделал - я думаю, что он сделал это в своем движке Sizzle, но я не уверен на 100%).
Я считаю, что выбор по идентификатору всегда быстрее:
$("#myform th").css("color","red");
должно быть быстрее, чем
$("th").css("color","red");
Однако мне интересно, насколько цепочка помогает при запуске с идентификатором? Это
$("#myform").find("th").css("color","red")
.end().find("td").css("color","blue");
быстрее, чем это?
$("#myform th").css("color","red");
$("#myform td").css("color","blue");
По моему опыту, $ ("# myform"). Find ("th") также быстрее, чем $ ("# myform th") из-за того, что первый напрямую делегирует собственный getElementByID браузера. Цепочка также помогает, но, по сути, накладные расходы - это стоимость второго вызова getElementByID, который обычно крошечный.
sizzle, механизм выбора jQuery работает справа налево. Итак, ваш первый пример: $ ("# myform th"). Css ("color", "red"); сначала находит все на странице. Затем он перебирает эти th и просматривает родителей для каждого, пока не найдет элемент с идентификатором myForm. Теоретически тогда ваш второй пример: $ ("th"). Css ("color", "red"); должен быть быстрее, чем ваш первый, так как он просто повторяет th, а не проверяет их родителей.
Как сказал Рид выше, jQuery работает снизу вверх. Несмотря на то что
that means
$('#foo bar div')is a lot slower than$('bar div #foo')
Не в этом дело. Если бы у вас был #foo, вы бы все равно ничего не ставили перед ним в селекторе, поскольку идентификаторы должны быть уникальными.
Дело в том:
.find, .children и т. д .: $('#foo').find('div')$('div.common[slow*=Search] input.rare'), а не $('div.rare input.common[name*=slowSearch]'), поскольку это не всегда применимо, убедитесь, что вы установили селекторный порядок, разделив его соответствующим образом.
Но даже если браузер реализует эту функцию, все равно будет быстрее фильтровать по имени тега, верно?