matches とは何か
matches は、ある要素が「指定した CSS セレクタに現在一致しているか」を真偽値で返すメソッドです。ここが重要です:取得した要素に対して直接判定できるため、「このクリック元がターゲットか」「このカードはアクティブ条件に合うか」などを高速・簡潔に書けます。セレクタは querySelector と同じ文法で使えます。
基本の使い方(その場でセレクタ適合をチェック)
単純な判定
<button class="btn primary">購入</button>
<script>
const btn = document.querySelector("button");
console.log(btn.matches(".btn")); // true
console.log(btn.matches(".secondary")); // false
console.log(btn.matches("button.primary")); // true
</script>
HTML要素を探してから「この要素が条件に合うか」を即判定できます。ここが重要です:matches は「再検索せずに済む」ので、読みやすく効率的です。
状態に依存する判定(擬似クラス)
<input id="agree" type="checkbox" checked>
<script>
const box = document.querySelector("#agree");
console.log(box.matches(":checked")); // true(現時点の状態)
</script>
HTML擬似クラスも使えます。現在の状態に応じた分岐がシンプルに書けます。
イベント委譲での実践(ターゲット判定の定番)
親一箇所にだけイベントを登録
<ul id="menu">
<li><button class="item" data-key="a">A</button></li>
<li><button class="item" data-key="b">B</button></li>
</ul>
<script defer>
const menu = document.getElementById("menu");
menu.addEventListener("click", (e) => {
const target = e.target;
if (!(target instanceof Element)) return;
if (target.matches("button.item")) {
const key = target.dataset.key;
console.log("clicked:", key);
}
});
</script>
HTMLここが重要です:クリックの発生源が「欲しいボタンか」を matches で即チェック。親に一度だけイベントを置く“委譲”と相性が抜群で、要素の追加・削除にも強い設計になります。
closest と組み合わせる(発生源が深い位置でも安全)
深い位置でクリックされても祖先を特定して判定
<div class="card">
<button class="buy"><span>購入</span></button>
</div>
<script defer>
document.addEventListener("click", (e) => {
const el = e.target;
if (!(el instanceof Element)) return;
const btn = el.closest("button.buy");
if (btn && btn.matches(".buy")) {
// ここに購入ボタンの処理
}
});
</script>
HTMLここが重要です:span をクリックしても、closest でボタンを引き上げ、最後に matches で条件を確定。DOM 入れ子に強く、誤判定を防げます。
セレクタ設計の勘所(読みやすさと安定性を優先)
data-* を使うと変更に強い
<button class="btn" data-role="buy">購入</button>
<script>
const btn = document.querySelector(".btn");
if (btn.matches('[data-role="buy"]')) {
// 役割に基づいた処理
}
</script>
HTMLここが重要です:見た目用クラスより「役割フック(id や data-*)」で判定すると、レイアウト変更に強く保守性が上がります。matches のセレクタは短く明確に。
特殊文字を含む id/クラスはエスケープ
<div id="user.name"></div>
<script>
const el = document.querySelector("#user\\.name");
console.log(el.matches("#user\\.name")); // true
</script>
HTMLセレクタにドットやコロンが入る命名は避けるのが理想です。必要ならバックスラッシュでエスケープします。
よくある落とし穴(境界・対象の型・パフォーマンス)
テキストノードは matches できない
イベントの target はテキストノードの場合があります。必ず Element かどうかを確認してから使いましょう。
if (!(e.target instanceof Element)) return;
JavaScript範囲外のクリックを除外する
特定コンテナ内だけで動かしたい場合は、contains と併用します。
const root = document.querySelector(".root");
document.addEventListener("click", (e) => {
const t = e.target;
if (!(t instanceof Element)) return;
if (!root.contains(t)) return; // root外は無視
if (t.matches(".action")) { /* … */ }
});
JavaScriptここが重要です:型ガード(Element かどうか)と範囲ガード(contains)を癖にすると、イベント処理の安定性が格段に上がります。matches は軽い判定なので、必要に応じて何度でも使えますが、同じ複雑セレクタの再判定は避け、結果は変数に保持すると読みやすくなります。
実践例:フォームの検証と動的クラス切り替え
<form id="contact">
<input class="field" name="email" type="email">
<input class="field" name="name" type="text">
<button class="submit">送信</button>
</form>
<script defer>
const form = document.getElementById("contact");
form.addEventListener("input", (e) => {
const el = e.target;
if (!(el instanceof Element)) return;
if (el.matches('input.field[name="email"]')) {
el.classList.toggle("is-valid", el.validity.valid);
}
if (el.matches('input.field[name="name"]')) {
el.classList.toggle("is-valid", el.value.trim().length > 0);
}
});
form.addEventListener("click", (e) => {
const el = e.target;
if (!(el instanceof Element)) return;
if (el.matches("button.submit")) {
e.preventDefault();
// 送信処理…
}
});
</script>
HTMLここが重要です:イベントの発生源に対して matches で「どのフィールドか」を即判定し、条件に応じてクラスを切り替える。分岐は短く明確、DOM 構造変更にも強い形になります。
まとめ
matches は「この要素がセレクタに適合するか」を一瞬で判定できるメソッドです。イベント委譲との相性がよく、発生源の要素がターゲットかどうかを簡潔に判断できます。上方向の特定には closest、下方向の検索には querySelector を組み合わせ、セレクタは役割フック(id・data-*)で短く明確に。型ガードと範囲ガードを癖にすれば、初心者でも安全で読みやすいイベント処理・DOM 判定が書けるようになります。
