Как улучшить производительность селектора jQuery?

Я ищу способ улучшить производительность селектора при вызове jQuery. Конкретно такие вещи:

$("div.myclass") быстрее, чем $(".myclass")

Я бы подумал, что это возможно, но я не знаю, достаточно ли умен jQuery, чтобы ограничить поиск по имени тега и т. д. У кого-нибудь есть идеи, как сформулировать строку селектора jQuery для лучшей производительности?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
74
0
29 655
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

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

В любом случае я бы не стал особо беспокоиться об этом, если вы не запускаете этот селектор тысячи раз в секунду.

Если вы действительно обеспокоены, попробуйте провести сравнительный анализ и посмотреть, что быстрее.

Ответ принят как подходящий

Несомненно, что фильтрация по имени тега выполняется намного быстрее, чем фильтрация по имени класса.

Так будет до тех пор, пока все браузеры не реализуют изначально getElementsByClassName, как в случае с getElementsByTagName.

Но даже если браузер реализует эту функцию, все равно будет быстрее фильтровать по имени тега, верно?

Hoffmann 07.11.2009 21:54

Я обновил Компонентхаус.com/article-19 из ответа Джеффа, чтобы использовать последнюю версию jQuery, похоже, что из второго теста A и B имеют одинаковую производительность в Opera 10 и firefox 3.5. Я не мог заставить его работать в IE8 (хотя я и не пробовал много). Так что, похоже, я ошибся в своем предыдущем комментарии.

Hoffmann 08.11.2009 00:24

@hoffmann, наверное, нет. Если мы предположим, что обе эти функции реализованы с помощью b-деревьев, я не понимаю, почему getElementsByClassName будет работать медленнее ... Вам все равно придется создать индекс, прежде чем вы сможете использовать эту функцию ...

Evan Carroll 30.06.2010 02:51

@AlienWebguy: Смысл этого ответа в том, что некоторые браузеры не поддерживают getElementsByClassName, а это означает, что элемент каждый на странице необходимо протестировать для класса. Имейте в виду, что этот ответ был дан и в 2008 году. ; о)

user113716 27.07.2011 02:20

т.е. <= 8 не в счет - весь интернет отстой для этих людей;)

AlienWebguy 27.07.2011 02:23

@AlienWebguy: ваш тест неточно представляет большую страницу с множеством элементов DOM. Ваш тест выполняется быстрее благодаря более простому набору фильтров, а не более быстрому поиску.

Aren 04.10.2011 00:27

Я добавлю замечание, что в 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(), а не устанавливать контекст селектора, как в вашем первом примере.

David says reinstate Monica 06.11.2010 18:17

Вот как повысить производительность ваших селекторов jQuery:

Чтобы полностью понять, что быстрее, вы должны понимать, как работает синтаксический анализатор 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, который обычно крошечный.

peakxu 11.02.2012 20:33

sizzle, механизм выбора jQuery работает справа налево. Итак, ваш первый пример: $ ("# myform th"). Css ("color", "red"); сначала находит все на странице. Затем он перебирает эти th и просматривает родителей для каждого, пока не найдет элемент с идентификатором myForm. Теоретически тогда ваш второй пример: $ ("th"). Css ("color", "red"); должен быть быстрее, чем ваш первый, так как он просто повторяет th, а не проверяет их родителей.

Chris Spittles 23.04.2012 13:20

Как сказал Рид выше, 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]'), поскольку это не всегда применимо, убедитесь, что вы установили селекторный порядок, разделив его соответствующим образом.

Другие вопросы по теме