jQuery / Selector / :odd - 奇数インデックスの要素を選択するセレクター
jQueryの :odd は、選択した集合を0から数え、インデックスが1、3、5となる要素、つまり2番目・4番目・6番目を選びます。「奇数」という名前から見た目の1行目を想像すると、結果が逆に見えます。新しいコードでは通常のCSSセレクターで範囲を定め、.odd() で絞り込みます。
:odd の意味と .odd() への移行
:odd の公式文書ではjQuery 3.4から非推奨とされ、.odd() メソッドへの置き換えが案内されています。.odd()は3.5で追加され、引数を取らず、現在の集合の奇数インデックスだけを含む新しいjQueryオブジェクトを返します。非推奨と削除は異なります。この比較は3.7.1と4.0.0の両方で実行し、一致を確認しました。
$("#records > tbody > tr:odd") は $("#records > tbody > tr").odd() に置き換えられます。3.5より古い版にはこのメソッドがないため、アプリとプラグインの互換性を確認してから更新します。
| 式 | 数える基準 | 初期状態の結果 |
|---|---|---|
| tbodyのtrに :odd または .odd() | 選択したデータ行の集合、0始まり | r2, r4 |
| ヘッダーを含む全trに .odd() | ヘッダーがインデックス0 | r1, r3, r5 |
| tbodyのtr:nth-child(odd) | 各親の兄弟位置、1始まり | r1, r3, r5 |
ヘッダー付き表の完全な実行例
以下の全コードをUTF-8の odd-demo.html として保存し、ブラウザーで開きます。パッケージのインストールは不要ですが、CDN(Content Delivery Network、コンテンツ配信ネットワーク)から公式配布ファイルを読み込むインターネット接続が必要です。例では4.0.0を使用します。
theadにヘッダー1行、tbodyにデータ5行があります。IDは行を識別する名前であり、インデックスは現在の文書順と選択範囲で決まります。ボタンで条件を切り替えます。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Odd indexes in table rows</title>
<style>
body { font: 16px/1.6 sans-serif; margin: 24px; }
table { border-collapse: collapse; width: 100%; max-width: 600px; }
th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
tr.marked { background: #fff0b3; }
button { margin: 4px; padding: 8px; }
</style>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
</head>
<body>
<h1>Odd indexes in table rows</h1>
<table id="records">
<thead><tr id="heading"><th>Item</th><th>Amount</th></tr></thead>
<tbody>
<tr id="r1" class="eligible"><td>Item 1</td><td>10</td></tr>
<tr id="r2"><td>Item 2</td><td>20</td></tr>
<tr id="r3" class="eligible"><td>Item 3</td><td>30</td></tr>
<tr id="r4" class="eligible"><td>Item 4</td><td>40</td></tr>
<tr id="r5" class="eligible"><td>Item 5</td><td>50</td></tr>
</tbody>
</table>
<button type="button" id="data">Data rows .odd()</button>
<button type="button" id="all">Include header .odd()</button>
<button type="button" id="css">Data :nth-child(odd)</button>
<button type="button" id="prepend">Prepend one data row</button>
<button type="button" id="reset">Reset</button>
<p id="result" aria-live="polite"></p>
<script>
$(function () {
function show($chosen) {
$("#records tr").removeClass("marked");
$chosen.addClass("marked");
const ids = $chosen.map((_, row) => row.id).get().join(", ");
$("#result").text(`${ids || "none"} | ${$chosen.length}`);
}
function dataRows() {
show($("#records > tbody > tr").odd());
}
$("#data").on("click", dataRows);
$("#all").on("click", () => show($("#records tr").odd()));
$("#css").on("click", () => show($("#records > tbody > tr:nth-child(odd)")));
$("#prepend").on("click", function () {
if (!$("#extra").length) {
$("#records > tbody").prepend('<tr id="extra"><td>Extra item</td><td>0</td></tr>');
}
dataRows();
});
$("#reset").on("click", function () {
$("#extra").remove();
dataRows();
});
dataRows();
});
</script>
</body>
</html>
初期状態はデータ行だけを選んで.odd()を適用するため、Item 2とItem 4が強調され、次の結果になります。
r2, r4 | 2
範囲変更・行追加・リセットを確認する
- Data rows .odd() はtbody直下のtrだけを数えます。インデックス1と3により
r2, r4 | 2となります。 - Include header .odd() はtheadのtrも含めます。ヘッダーが0を占めるため
r1, r3, r5 | 3に変わります。 - Data :nth-child(odd) はtbody内の1・3・5番目の兄弟を選び、
r1, r3, r5 | 3となります。前のボタンと同じ結果でも、数える規則は異なります。 - Prepend one data row はtbodyの先頭にExtra itemを挿入して.odd()を再計算します。元のr1がインデックス1へずれ、
r1, r3, r5 | 3となります。extraのID確認により、繰り返し押しても重複しません。 - Reset は追加行だけを削除し、データ行に.odd()を再適用します。元の5行と値を保ち、
r2, r4 | 2に戻ります。
showは古いmarkedクラスをすべて外してから新しい集合を強調するため、強調が蓄積しません。実際の表でもIDと直接の親子関係で範囲を限定し、別の表や入れ子の表を含めないようにします。
CSSの odd と比べる
開いた直後かReset後に、開発者ツールのConsoleで次の部分コードを実行します。最初の2行が従来の選択子と代替メソッド、最後がCSSの規則に従う :nth-child()です。
const ids = $set => $set.map((_, row) => row.id).get().join(", ");
console.log(ids($("#records > tbody > tr:odd")));
console.log(ids($("#records > tbody > tr").odd()));
console.log(ids($("#records > tbody > tr:nth-child(odd)")));
r2, r4
r2, r4
r1, r3, r5
.odd()は選択集合全体を一続きに数えますが、:nth-child(odd)は親ごとに兄弟位置を数え直します。tbodyが複数ならそれぞれ先頭から計算します。:nth-child()はタグの種類に関係なく要素の兄弟を数え、その位置でtr条件も満たすものを残します。空白テキストやコメントは要素の兄弟に数えません。
フィルター順序と動的な行の注意点
eligibleクラスはr1・r3・r4・r5にあります。$("#records > tbody > tr.eligible").odd() は先にこの4行を集め、r3とr5を残します。全5行に.odd()を適用してから .filter(".eligible") を付けると、r2とr4のうちr4だけが残ります。順序によってインデックスの基準集合が変わります。
空集合や1要素だけの集合にはインデックス1がないので、.odd()の結果も空です。選択結果は自動更新されません。挿入前に保存したr2・r4の集合は、その後も同じ要素を保持します。現在位置を反映したければdataRowsのように再検索します。
反応がなければNetworkのjQuery読み込み、Consoleのエラー、jQuery.fn.jquery を確認します。結果が逆ならヘッダーの包含、tbodyの範囲、フィルター順序、追加行の有無を調べます。見た目の行番号と0始まりのインデックスを分けて考えてください。




