Селекторы и Sizzle
Пропустите это раздел, и вернитесь к нему тогда, когда вас заинтересует, как происходит поиск элементов внутри $(...)
В качестве «поисковика» по элементам DOM jQuery использует библиотеку Sizzle. Данная библиотека одно время была неотъемлемой частью jQuery, затем «отпочковалась» в отдельный проект, который с радостью используется как самим jQuery, так и Dojo Toolkit. Но хватит лирики, давайте перейдем непосредственно к поиску. Для оного в JavaScript'е предусмотрены следующие методы (не в jQuery, не в Sizzle, а в JavaScript):
getElementById(id)
поиск по id="…"
getElementsByName(name)
поиск по name="name"
и id="name"
getElementsByClassName(class)
поиск по class="class"
getElementsByTagName(tag)
поиск по имени тега
querySelectorAll(selector)
поиск по произвольному CSS-селектору
Пробежавшись беглым взглядом по списку, можно заметить метод querySelectorAll()
– он универсален и действительно удобен. И именно этот метод библиотека пытается вызвать, когда вы скармливаете что-то в качестве селектора в jQuery, но данный метод иногда нас подводит, и тогда на сцену выходит Sizzle во всей красе, вооруженный всеми упомянутыми методами, да ещё со своим уникальным арсеналом:
Но давайте уже рассмотрим, как Sizzle ищет в DOM, если-таки метод document.querySelectorAll()
споткнулся. Начнём с разбора алгоритма работы на следующем примере:
Получить первое выражение до запятой: «
thead > .active
»Разбить на кусочки: «
thead
», «>
», «.active
»Найти исходное множество элементов по последнему кусочку (все «
.active
»)Фильтровать справа налево (все «
.active
» которые находятся непосредственно в «thead
»)Искать следующий запрос после запятой (возвращаемся к первому пункту)
Оставить только уникальные элементы в результате
Глядя на данный алгоритм вы должны заметить, что правила читаются справа налево!
Копаем глубже. При анализе даже самого маленького выражения есть несколько нюансов, на которые стоит обратить внимание. Первый – это приоритет поиска, он различен для различных браузеров (в зависимости от их возможностей, или «невозможностей»):
Не обращайте внимание на RegExp – это внутренняя кухня Sizzle.
Таким образом, рассматривая выражение div#my
, Sizzle найдёт вначале элемент с id="my"
, а потом уже проверит на соответствие с <div>
. Хорошо, это вроде как фильтрация, и она тоже соблюдает очерёдность – это второй нюанс:
Третий нюанс – это относительные фильтры, которые работают сразу с двумя элементами (они вам знакомы по CSS-селекторам):
Ой, зачем я вас всем этим гружу? Почитайте лучше об оптимизации запросов в следующем главе.
Официальная документация по библиотеке Sizzle доступна на GitHub'е проекта.
Last updated