記事内の段落
タイトル: .find()
SEOタイトル: jQuery .find() 完全ガイド(子孫検索、.children() / .closest() との違い、querySelectorAll)
| この記事の要点 |
|
.find() の基本
jQuery .find() は、マッチした要素の子孫からセレクタに一致する要素を抽出します。直下の子のみではなく、孫・ひ孫まで深く探索します。
直下の段落
セクション内の段落
// 子孫すべての p
$('#wrap').find('p').length; // → 3
// 直下の p のみ
$('#wrap').children('p').length; // → 1
// セレクタ必須 (省略すると空)
$('#wrap').find(); // → 空オブジェクト
.find() vs .children() vs .closest()
| メソッド | 方向 | 対象 | 用途例 |
|---|---|---|---|
.find(s) | 下向き | 子孫全要素 | 表内の全 input を集める |
.children(s) | 下向き | 直下の子のみ | リストの件数カウント |
.closest(s) | 上向き | 自身含む最も近い祖先 | クリックされた行の tr 特定 |
.parents(s) | 上向き | 祖先すべて | 祖先の form をすべて取る |
.siblings(s) | 横方向 | 兄弟要素 | 選択肢の他を非アクティブ化 |
複数セレクタとフィルタ
// カンマで複数指定
$('#form').find('input, select, textarea');
// 属性セレクタ
$('table').find('[data-id]');
// :checkbox / :radio / :hidden / :visible
$('form').find(':checkbox:checked');
// jQuery オブジェクトを引数に取れる
const $targets = $('.item');
$('#wrap').find($targets); // wrap 配下の .item
// DOM 要素も渡せる
$('#wrap').find(document.querySelector('.target'));
典型的なユースケース
1. テーブル全行の値を集計
const total = $('#cart').find('.price').toArray()
.map(el => parseInt($(el).text(), 10))
.reduce((a, b) => a + b, 0);
$('#total').text(total.toLocaleString());
2. 動的に挿入した要素にも対応
$('#chat').on('messageAdded', function() {
// 最新追加分を含めて取り直す
$(this).find('.message').addClass('animated fadeIn');
});
// イベント委譲 (find したのと同じ要素群に効く)
$('#chat').on('click', '.message', function() {
$(this).toggleClass('selected');
});
3. フォーム内の全入力値を取得
const $form = $('#myForm');
const data = {};
$form.find(':input').each(function() {
data[this.name] = $(this).val();
});
// または serializeArray
const data2 = $form.serializeArray();
生 DOM API での同等処理
const wrap = document.getElementById('wrap');
// 子孫全件 (find 相当)
wrap.querySelectorAll('p'); // 3 件
wrap.querySelectorAll('input, select');
// 1 件目だけ (find().first() 相当)
wrap.querySelector('.first-item');
// closest (祖先方向)
document.querySelector('.btn').closest('form');
// :scope で「自身から見て」を明示
wrap.querySelectorAll(':scope > p'); // 直下のみ
wrap.querySelectorAll(':scope > * > p'); // 孫のみ
// matches で自身がセレクタにマッチするか確認
wrap.matches('.parent'); // boolean
パフォーマンスと最適化
| パターン | 速度 | 備考 |
|---|---|---|
$("#a .b") | 速い | jQuery 内部で Sizzle / querySelectorAll |
$("#a").find(".b") | 同等〜速い | キャッシュ済の親があれば再利用しやすい |
$(".b", "#a") | 遅い | 古い書き方、内部で find に変換される |
el.querySelectorAll(".b") | 最速 | ネイティブ |
| 自前 for ループ | 最遅 | JS 側で再帰探索すると桁違いに遅い |
大量の DOM に対して何度も検索するなら、結果をキャッシュして再利用するのが基本です。
// ❌ 毎回探す
$('#tbl').find('tr').each(function() {
$('#tbl').find('tr').first().addClass('header'); // ループ内で再検索
});
// ✅ キャッシュ
const $rows = $('#tbl').find('tr');
$rows.first().addClass('header');
$rows.slice(1).addClass('body');
現代の DOM 選択 API
| jQuery | ネイティブ |
|---|---|
$(sel).find(s) | el.querySelectorAll(s) |
$(sel).children(s) | el.querySelectorAll(":scope > " + s) |
$(sel).closest(s) | el.closest(s) |
$(sel).parent() | el.parentElement |
$(sel).is(s) | el.matches(s) |
FAQ
Q: .find() は自身を含む?
A: 含みません。自身も対象にしたい場合は .find('selector').addBack() や .add('selector')。
Q: .find() で複数の結果が来たときに 1 件だけ欲しい
A: .first() / .eq(0) / .last() / .eq(-1) でフィルタ。
Q: ネイティブ querySelectorAll とどちらを使う?
A: 新規開発ならネイティブ推奨。jQuery 既存コードを保守するなら統一感のため .find() を使い続けます。