JavaScript | 配列・オブジェクト:配列の検索・判定 – indexOf

JavaScript JavaScript
スポンサーリンク

indexOf とは何か

indexOf は「配列の中から、指定した値が最初に現れる位置(インデックス)を返す」検索メソッドです。見つかれば 0 以上の番号、見つからなければ -1 を返します。ここが重要です:indexOf の比較は厳密等価(===)。型が違えば一致しませんし、オブジェクトは“同じ参照”でない限り一致しません。


基本の使い方と戻り値

見つかったときの挙動

const a = ["pen", "book", "note"];
const i = a.indexOf("book");
console.log(i);    // 1(0始まり)
console.log(a[i]); // "book"
JavaScript

ここが重要です:返ってきたインデックスをそのまま使って要素を参照できます。0 始まりなので、1 は“2番目”の意味です。

見つからないとき(-1 の扱い)

const a = ["pen", "book", "note"];
const i = a.indexOf("pencil");
console.log(i); // -1(未検出)
if (i === -1) {
  // 見つからなかったときの処理
}
JavaScript

ここが重要です:-1 は「無い」という明確なシグナル。if (i >= 0) で“見つかった”と判定するのが定石です。


厳密比較と型・参照の注意

型が違うと一致しない(===)

const nums = [1, 2, 3];
console.log(nums.indexOf("2")); // -1("2" は文字列、2 は数値)
JavaScript

ここが重要です:indexOf は型も比較します。文字列 “2” と数値 2 は別物です。期待する型で検索しましょう。

オブジェクト・配列は“同じ参照”だけ一致

const obj = { id: 1 };
const a = [obj, { id: 1 }];
console.log(a.indexOf(obj));        // 0(同じ参照)
console.log(a.indexOf({ id: 1 }));  // -1(別インスタンス)
JavaScript

ここが重要です:中身が同じでも別インスタンスは一致しません。プロパティで探したいときは findIndex を使います。

NaN は見つからない(NaN !== NaN)

console.log([NaN].indexOf(NaN)); // -1
JavaScript

ここが重要です:NaN は自分自身とも等しくないため、indexOf では検出できません。必要なら includes(NaN を見つけられる)や findIndex と Number.isNaN を使います。

[NaN].includes(NaN); // true
[NaN].findIndex(Number.isNaN); // 0
JavaScript

開始位置 fromIndex と負の値

fromIndex で検索の開始位置を指定

const a = ["A", "B", "A", "C"];
console.log(a.indexOf("A"));      // 0(最初)
console.log(a.indexOf("A", 1));   // 2(インデックス1から検索)
JavaScript

ここが重要です:同じ値が複数あるとき、“次を探す”のに有効です。前回の位置+1 を開始位置にすると連続検索ができます。

fromIndex が負の値(末尾からの相対開始)

const a = ["A", "B", "A", "C"];
console.log(a.indexOf("A", -2)); // 2(最後から2の位置=インデックス2から検索)
JavaScript

ここが重要です:負の fromIndex は「末尾からの相対位置」。計算後 0 未満になれば 0 に切り上げられます(つまり“先頭から”検索になります)。


関連メソッドの使い分け

includes(あるかどうかだけ知りたい)

const a = ["pen", "book"];
a.includes("book"); // true(位置は不要、存在判定が目的ならこちら)
JavaScript

ここが重要です:位置が不要なら includes のほうが意図が明確で、NaN にも対応します。

lastIndexOf(最後に現れる位置)

const a = ["A", "B", "A"];
console.log(a.lastIndexOf("A")); // 2(末尾側からの最初=“最後の位置”)
JavaScript

ここが重要です:重複があり“最後の発生位置”を取りたいときに使えます。

findIndex(条件で探す)

const users = [{id:1},{id:2}];
const i = users.findIndex(u => u.id === 2); // 1
JavaScript

ここが重要です:プロパティや複合条件で探したいなら findIndex。indexOf は“値そのもの”が一致する場合に使います。


実践例(削除・置き換え・重複対策)

指定の値を削除する(見つけてから splice)

const items = ["pen", "book", "note"];
const i = items.indexOf("book");
if (i >= 0) items.splice(i, 1);
console.log(items); // ["pen", "note"]
JavaScript

ここが重要です:必ず位置を確認してから削除。-1 のまま splice すると末尾付近の意図しない削除になります。

指定の値を別の値に置き換える

const colors = ["red", "green", "blue"];
const i = colors.indexOf("green");
if (i >= 0) colors[i] = "lime";
JavaScript

ここが重要です:位置さえ分かれば更新は簡単。存在しなければ追加するなど、分岐で意図を明確にしましょう。

存在判定して重複追加を防ぐ

const tags = ["js", "web"];
const next = tags.includes("ux") ? tags : [...tags, "ux"];
JavaScript

ここが重要です:位置が不要なら includes で十分。非破壊で追加する習慣を持つと副作用を避けられます。


よくある落とし穴と回避策

  • 型違いの比較ミス: “2” と 2 は一致しません。検索前に型を確認・揃えましょう。
  • オブジェクト比較の誤解: 内容が同じでも別インスタンスは一致しません。条件検索は findIndex を使います。
  • NaN が見つからない: indexOf は NaN を検出できません。includes や findIndex(Number.isNaN) を使います。
  • -1 の扱いミスで誤削除: -1 のまま splice すると末尾付近を削る事故に。必ず i >= 0 を条件にします.
  • 重複に対して indexOf をループで乱用: すべての重複を消したいなら filter のほうが簡潔です。 const xs = ["A","B","A"]; const withoutA = xs.filter(x => x !== "A"); // ["B"]

まとめ

indexOf は「値そのものを厳密等価で比較して、最初の位置を返す」メソッドです。見つからなければ -1、開始位置は fromIndex で指定可、負の値は末尾からの相対。型違い・参照比較・NaN という“比較のクセ”を理解し、位置が不要なら includes、条件検索なら findIndex、最後の位置なら lastIndexOf を使い分けましょう。削除や置換では“位置確認してから操作”を徹底すれば、初心者でも安全で意図通りの検索・判定が書けます。

タイトルとURLをコピーしました