indexOfは連想配列で使えない?理由と正しい対処法

プログラミング学習

JavaScriptやTypeScriptを学んでいると、配列の要素を探すときに
「とりあえず indexOf を使えばいい」
と考えがちです。

しかし、実装を進めていると次のような疑問にぶつかります。

  • オブジェクト(連想配列)に indexOf が使えない
  • 期待した位置が返ってこない
  • -1 になる理由が分からない

私自身、未経験からIT企業への転職に向けてTypeScriptを学ぶ中で、
ToDoリストのデータ管理をしている際にこの問題に直面しました。

結論から言うと、
indexOf は「配列専用」であり、連想配列(オブジェクト)では使えません。

この記事では、その理由と、
indexOfが使えない場合の正しい対処法 を整理します。


indexOfは何をしているメソッドなのか

まず前提として、indexOf配列のメソッド です。

const arr = ["a", "b", "c"];
arr.indexOf("b"); // 1

このとき、indexOf
配列の中身を先頭から順番に比較し、完全一致した要素の位置を返す
という処理をしています。

重要なのは、
値そのものを比較している
という点です。


なぜ連想配列(オブジェクト)では使えないのか

そもそも連想配列は「配列ではない」

JavaScriptでよく言われる「連想配列」は、正確には オブジェクト です。

const task = {
  id: 1,
  title: "勉強する",
  done: false
};

この構造は、

  • 順番を持つ配列
  • 数字のインデックス

ではなく、
キーと値の組み合わせ で管理されています。

そのため、配列専用メソッドである indexOf は使えません。


オブジェクトを配列に入れた場合でも注意が必要

次のようなケースも、初心者がよく混乱します。

const tasks = [
  { id: 1, title: "勉強する" },
  { id: 2, title: "運動する" }
];

tasks.indexOf({ id: 1, title: "勉強する" }); // -1

一見すると同じオブジェクトに見えますが、
indexOf参照(メモリ上の同一性) を比較します。

つまり、

  • 中身が同じ
  • でも別のオブジェクト

という場合、見つからないのが正しい挙動です。


indexOfが使えないときの正しい対処法

findIndexを使う(最もよく使う)

オブジェクトの配列から特定の要素を探す場合、
最も一般的なのが findIndex です。

const index = tasks.findIndex(t => t.id === 1);

この方法なら、

  • オブジェクトのプロパティで比較できる
  • 条件を自由に書ける

というメリットがあります。


findを使って要素そのものを取得する

「位置」ではなく「中身」が欲しい場合は find を使います。

const task = tasks.find(t => t.id === 1);

ToDoリストなどでは、
indexよりも要素そのものが必要な場面の方が多い
ため、こちらの方が自然なケースも多いです。


filterを使って複数取得する

条件に合うものが複数ある可能性がある場合は、filter を使います。

const doneTasks = tasks.filter(t => t.done === true);

これは indexOf では実現できない使い方です。


オブジェクト単体ならキーで直接アクセスする

配列ではなく、単なるオブジェクトであれば、
そもそも探す必要はありません。

const task = {
  id: 1,
  title: "勉強する"
};

console.log(task.title);

このように、
キーが分かっているなら直接アクセスする
のが最もシンプルです。


なぜこの理解が重要なのか

indexOfが使えない問題は、
単なるメソッドの知識不足ではありません。

  • 配列とオブジェクトの違い
  • 値と参照の違い
  • データ構造の選び方

これらを理解していないと、
バグの原因になります。

特にReactやTypeScriptで状態管理を行う場合、
「配列の中のオブジェクトをどう特定するか」
は頻出テーマです。


まとめ

indexOf が使えるのは、

  • プリミティブ値
  • 同一参照の要素
  • 純粋な配列

だけです。

連想配列(オブジェクト)や、
オブジェクトの配列を扱う場合は、

  • findIndex
  • find
  • filter

を使うのが正解です。

未経験からTypeScriptを学ぶ中で感じたのは、
「メソッドを覚えるより、データ構造を理解する方が大事」
ということでした。

コメント

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