Jquery функция $.find()

Определение и применение

Функция $.find() находит DOM-элементы по селектору и возвращает их без обёртки jQuery. Она полезна, когда компонент уже работает с обычными элементами, но ему нужны селекторы jQuery. Например, плагин может найти товары внутри своего контейнера, отобрать часть заранее собранного массива или проверить одну карточку.

Для обычной цепочки действий удобнее .find(): метод вызывается у коллекции и возвращает коллекцию. Низкоуровневые функции ниже рассматриваются для полной jQuery 4.0.0.

Синтаксис и результат

JavaScript
const elements = $.find(selector, context, results);
const filtered = $.find.matches(selector, elements);
const matches = $.find.matchesSelector(element, selector);
Три задачи движка селекторов
ВызовЧто делаетРезультат
$.find(selector, context)Ищет элементы внутри контекстаМассив DOM-элементов
$.find.matches(selector, elements)Фильтрует переданный массив элементовМассив подходящих элементов
$.find.matchesSelector(element, selector)Проверяет один DOM-элементtrue или false

selector — строка селектора. Для $.find() контекстом служит DOM-элемент, документ или DocumentFragment; если его не передать, поиск начинается в document. Передавайте container или $(container)[0], а не объект $(container). Для поиска по обычному селектору элемент-контекст сам в результат не включается.

Необязательный results — массив или совместимый объект с length и push. Функция дописывает найденные элементы в него и возвращает этот же объект. Уже находящиеся там элементы не очищаются. Повторные вызовы с одним массивом могут накопить дубликаты; для независимого поиска не передавайте старый массив.

У matches() порядок аргументов начинается с селектора, а у matchesSelector() — с элемента. Пустой массив для фильтрации даёт пустой результат. Не передавайте вместо элемента null: сначала проверьте, что поиск элемента завершился успешно.

В первом контейнере находятся два товара, во втором — ещё один. Пример ищет доступные товары только в первом контейнере, затем фильтрует массив из обоих контейнеров и отдельно проверяет первую карточку. Результаты показывают, что область поиска и исходный массив — разные ограничения.

Найти товары в контейнере и отфильтровать массив: попробуйте сами

index.html
HTML
<section id="first">
  <h2>Первый каталог</h2>
  <p class="product available">Книга</p>
  <p class="product">Карандаш</p>
</section>
<section id="second">
  <h2>Второй каталог</h2>
  <p class="product available">Блокнот</p>
</section>
<pre id="result" aria-label="Результат поиска"></pre>
main.js
JavaScript
const first = document.getElementById('first');
const all = Array.from(document.querySelectorAll('.product'));
const names = elements => elements.map(element => element.textContent.trim()).join(', ');
const found = $.find('.product.available', first);
const filtered = $.find.matches('.available', all);
const isAvailable = $.find.matchesSelector(all[0], '.available');
const accumulated = [all[1]];
const returned = $.find('.product.available', first, accumulated);

document.getElementById('result').textContent = [
  'В первом каталоге: ' + names(found),
  'В общем массиве: ' + names(filtered),
  'Книга доступна: ' + isAvailable,
  'С добавлением к массиву: ' + names(accumulated),
  'Возвращён тот же массив: ' + (returned === accumulated),
  'Массив: ' + Array.isArray(found),
  'Коллекция jQuery: ' + ($(first).find('.available').jquery === $.fn.jquery)
].join('\n');

Ожидаемый результат: поиск внутри первого контейнера находит «Книгу», фильтрация общего массива — «Книгу» и «Блокнот». Проверка книги возвращает true. У коллекции $(first).find() есть методы jQuery, у массива из $.find() — обычные методы массива. Чтобы применить метод jQuery к найденным узлам, явно оберните результат: $(elements).addClass("selected").

Собственный псевдокласс через $.expr

Псевдокласс — условие выбора элемента после двоеточия в селекторе. В jQuery можно добавить своё условие через $.expr.pseudos. Без аргумента оно представляет собой функцию проверки элемента. Для условия с аргументом используйте $.expr.createPseudo(): фабрика получает текст аргумента и возвращает функцию проверки.

Во втором примере :catalogAvailable проверяет наличие товара, а :catalogMinPrice(100) — минимальную цену. Фабрика один раз преобразует аргумент в число; затем проверяющая функция сравнивает его с ценой каждой карточки.

Добавить условия наличия и минимальной цены: попробуйте сами

index.html
HTML
<section id="catalog">
  <h2>Каталог</h2>
  <p class="product" data-stock="yes" data-price="120">Книга</p>
  <p class="product" data-stock="yes" data-price="20">Карандаш</p>
  <p class="product" data-stock="no" data-price="200">Альбом</p>
</section>
<pre id="result" aria-label="Результат фильтрации"></pre>
main.js
JavaScript
$.expr.pseudos.catalogAvailable = element => element.dataset.stock === 'yes';
$.expr.pseudos.catalogMinPrice = $.expr.createPseudo(argument => {
  const minimum = Number(argument);
  return element => {
    const price = element.dataset.price;
    return price !== undefined && price !== '' && Number.isFinite(minimum) &&
      Number.isFinite(Number(price)) && Number(price) >= minimum;
  };
});

const selected = $.find('.product:catalogAvailable:catalogMinPrice(100)', document.getElementById('catalog'));
document.getElementById('result').textContent = 'Доступны от 100: ' +
  selected.map(element => element.textContent.trim()).join(', ');

Среди доступных товаров ценой от 100 остаётся только «Книга». Эти псевдоклассы существуют в движке jQuery: передавать их напрямую в querySelectorAll() нельзя. Регистрация глобальна для экземпляра jQuery, поэтому выбирайте имя с префиксом своего компонента и не переопределяйте встроенные имена. Условие проверки не должно менять DOM.

Если правило используется в одном месте, обычно проще $(elements).filter(elementPredicate). Помните, что у функции, переданной в .filter(), первый аргумент — индекс, а элемент — второй; её сигнатура отличается от функции в $.expr.pseudos.

Ограничения и типичные ошибки

  • Обычный поиск по стандартному CSS-селектору часто можно решить через querySelectorAll(), а проверку элемента — через element.matches(). Подключать jQuery только ради этого не требуется.
  • Селектор и набор элементов — разные данные. Не собирайте селектор из произвольного пользовательского текста. Для динамического идентификатора экранируйте именно его значение через $.escapeSelector(); ошибочный синтаксис селектора может вызвать исключение.
  • Результаты не являются живым списком: после добавления карточки в DOM нужно повторить поиск. Фильтрация готового массива не добавляет в него новых потомков.
  • Позиционные условия вроде :first относятся к набору элементов. Для проверки отдельной карточки выбирайте условие, описывающее сам элемент, например класс или атрибут.

Что проверено для jQuery 4.0

В исходниках 4.0.0 сохранены $.expr.pseudos и $.expr.createPseudo(). Старые инструкции с $.expr.order, $.expr.match.POS и прежней сигнатурой setFilters нельзя механически переносить из документации Sizzle. Внутренние $.find.compile, select, setDocument и tokenize оставлены для обратной совместимости; сама реализация помечает их приватными. Для прикладного кода используйте описанные выше операции, а не внутренний компилятор.

Документация