JavaScript | 基礎構文:文字列操作 – 検索(indexOf / includes)

JavaScript JavaScript
スポンサーリンク

文字列の「検索」を一言でいうと

文字列の検索は、
「この文字(文字列)が含まれているか?」
「含まれているなら、どの位置にあるか?」

を調べることです。

JavaScript では、そのために主に
indexOfincludes という 2 つのメソッドを使います。

indexOf は「位置が知りたいとき」
includes は「含まれているかどうかだけ知りたいとき」

このイメージを持っておくと整理しやすいです。

ここが重要です。
条件分岐(if)と組み合わせたとき、
indexOf は「位置 or -1」、includes は「true / false」
という結果を返す、という違いをしっかり押さえると、一気に使い分けが楽になります。


indexOf の基本:最初に見つかった位置(インデックス)を返す

indexOf の基本構文と戻り値

indexOf の書き方はこうです。

文字列.indexOf(検索したい文字列)
JavaScript

戻り値は「最初に見つかった位置のインデックス」です。
もし見つからなければ -1 が返ってきます。

例を見てみましょう。

const text = "JavaScript";

console.log(text.indexOf("Java"));  // 0
console.log(text.indexOf("Script")); // 4
console.log(text.indexOf("a"));      // 1(最初に見つかった "a" の位置)
console.log(text.indexOf("z"));      // -1(見つからない)
JavaScript

"JavaScript" のインデックスはこうなっています。

J(0) a(1) v(2) a(3) S(4) c(5) r(6) i(7) p(8) t(9)

"Java" は 0 から始まる
"Script" は 4 から始まる
"a" は最初に 1 の位置にある

だから上のような結果になるわけです。

見つからないときは -1 になる(ここが大事)

indexOf は、検索対象が見つからないときに -1 を返します。

const text = "hello";

console.log(text.indexOf("x")); // -1
JavaScript

ここで 0nullundefined ではなく、
必ず -1 という値になります。

ここが重要です。
「見つかったかどうか」を indexOf で判断するときは、
=== -1!== -1 を使う。
if (text.indexOf("a")) { ... } のように “そのまま if に突っ込む” のはバグの元です。

「見つかったかどうか」を indexOf で書く場合

例えば、「text"a" が含まれているか?」を調べたいとします。

間違った書き方はこうです。

if (text.indexOf("a")) {
  // これだと index が 0 のとき(先頭にあるとき)に false とみなされてしまう
}
JavaScript

indexOf0 を返した場合、
0 は falsy(false 相当)なので if に入らなくなります。

正しい書き方はこうです。

if (text.indexOf("a") !== -1) {
  console.log("a が含まれています");
} else {
  console.log("a は含まれていません");
}
JavaScript

もしくは逆向きに、

if (text.indexOf("a") === -1) {
  console.log("a は含まれていません");
}
JavaScript

のように書きます。


indexOf の応用:検索開始位置(第2引数)

第2引数で「どこから検索を始めるか」を指定できる

indexOf には、第2引数を渡すことができます。

文字列.indexOf(検索文字列, 開始位置)
JavaScript

開始位置より前の部分は無視して、
そこから後ろだけを対象に検索します。

例:

const text = "banana";

//            b(0) a(1) n(2) a(3) n(4) a(5)

console.log(text.indexOf("a"));      // 1   (最初の a)
console.log(text.indexOf("a", 2));   // 3   (インデックス 2 以降で最初の a)
console.log(text.indexOf("a", 4));   // 5   (インデックス 4 以降で最初の a)
console.log(text.indexOf("a", 6));   // -1  (6 以降には a がない)
JavaScript

「1 個目の a」「2 個目の a」「3 個目の a」と順番に探したいときなどに使えます。

全出現箇所を見つける処理のイメージ

例えば、「文字列中の "a" がある位置を全部知りたい」とします。

const text = "banana";
let index = text.indexOf("a");

while (index !== -1) {
  console.log("a が見つかった位置:", index);
  index = text.indexOf("a", index + 1);
}
JavaScript

出力は

0, 2, 4
…ではなく、"banana" では

b(0) a(1) n(2) a(3) n(4) a(5)

なので、1, 3, 5 になります。

こうやって、「見つかった位置の次から再検索する」ことで、
複数の出現箇所を順番にたどることができます。

ここが重要です。
第2引数付き indexOf は「部分的にスキップしてから検索する」道具。
1回だけでなく、「次の位置からもう一度 indexOf」というパターンで、複数箇所を探せる。


includes の基本:「含まれているかどうか」だけが知りたいとき

includes の基本構文と戻り値

includes の書き方はこうです。

文字列.includes(検索したい文字列)
JavaScript

戻り値はシンプルで、
含まれていれば true、含まれていなければ false です。

例:

const text = "JavaScript";

console.log(text.includes("Java"));   // true
console.log(text.includes("Script")); // true
console.log(text.includes("java"));   // false(大文字小文字は区別される)
console.log(text.includes("Python")); // false
JavaScript

indexOf で書いていた「含まれているか判定」を、includes なら素直に書ける

さきほどの「a が含まれているか?」のチェックを
includes で書くと、かなり読みやすくなります。

const text = "banana";

if (text.includes("a")) {
  console.log("a が含まれています");
} else {
  console.log("a は含まれていません");
}
JavaScript

これだけです。

indexOf だと:

if (text.indexOf("a") !== -1) { ... }
JavaScript

となり、
!== -1 の意味を知らないと「何をやっているのか」が分かりにくいですよね。

ここが重要です。
「含まれているかどうか」だけを知りたいときは includes のほうが明らかに読みやすい。
indexOf の -1 を意識せずに済むので、バグも減ります。

includes も第2引数で開始位置を指定できる

includes にも第2引数があります。

文字列.includes(検索文字列, 開始位置)
JavaScript

indexOf と同じように、そこから後ろだけを対象に検索します。

const text = "banana";

//         b(0) a(1) n(2) a(3) n(4) a(5)

console.log(text.includes("a", 2)); // true(インデックス2以降に a はある)
console.log(text.includes("a", 4)); // true(インデックス4以降にも a はある)
console.log(text.includes("a", 6)); // false(6 以降には a はない)
JavaScript

ただし、「どこにあるか」までは教えてくれません。
あくまで「あるか/ないか」だけです。


indexOf と includes の使い分け

「位置」が欲しいなら indexOf

次のようなときは、indexOf が必要です。

特定の文字列が、どこに現れたか知りたい
見つかった位置からさらに操作したい(そこから先を slice したいなど)
複数の出現箇所を走査したい

例えば:

const url = "https://example.com/users/12345";

const index = url.indexOf("/users/");
if (index !== -1) {
  const userId = url.slice(index + "/users/".length);
  console.log(userId); // "12345"
}
JavaScript

"/users/" がどの位置にあるか」を知って、その位置をもとにslice` しています。
こういう用途では indexOf が必須です。

「あるかどうか」だけなら includes

次のようなときは includes で十分です。

メールアドレスに "@" が含まれているかざっくりチェック
ファイル名に ".png"".jpg" が含まれているか確認
文章に NG ワードが含まれているかどうか

例:

const email = "user@example.com";

if (!email.includes("@")) {
  console.log("メールアドレスの形式が怪しいです");
}
JavaScript

位置情報まで必要ないので、
indexOf で !== -1 と書くより、
includes のほうが意図が伝わります。

includes を使えない環境の話(補足)

かなり古いブラウザ(古い IE など)では includes が使えないことがありましたが、
現代の開発ではほぼ気にしなくて大丈夫です。

もしどうしても includes が使えない環境を相手にするなら、
indexOf(...) !== -1 で代替できる、と覚えておけば OK です。

ここが重要です。
基本方針としては
「位置が必要 → indexOf」
「存在チェックだけ → includes」
と覚えておけば、ほとんどのケースを迷わず書き分けられます。


大文字・小文字の扱いに注意(どちらも区別する)

indexOf も includes も大文字・小文字を区別する

例を見てください。

const text = "JavaScript";

console.log(text.includes("java"));  // false
console.log(text.indexOf("java"));   // -1
JavaScript

"JavaScript" の中に "java"(全部小文字)は含まれていない、と判断されます。

"Java"(先頭だけ大文字)と "java" は、別物です。

大文字小文字を区別したくない場合(簡易版)

「大文字小文字を無視して検索したい」なら、
両方とも toLowerCase()toUpperCase() で揃えてから検索します。

const text = "JavaScript";

const lower = text.toLowerCase();

console.log(lower.includes("java"));       // true
console.log(lower.indexOf("script"));      // 4
JavaScript

もちろん、検索する側も同様に揃えます。

const query = "JaVa";
const text = "javascript";

if (text.toLowerCase().includes(query.toLowerCase())) {
  console.log("含まれています");
}
JavaScript

ここが重要です。
indexOf も includes も、標準では「大小文字を区別する」。
大文字小文字を区別せず検索したいときは、
toLowerCase()toUpperCase() を組み合わせるのが基本パターンです。


初心者が本当に押さえるべきポイントまとめ

indexOf は「最初に見つかった位置」を返す。
見つからないときは -1
「含まれているかどうか」の判定に使うときは、
!== -1 / === -1 で比較する。

includes は「含まれているかどうかだけ」を返す。
結果は true / false なので、if 文と組み合わせると読みやすい。

2つ目の引数で「検索開始位置」を指定できるが、
位置が欲しいなら indexOf、存在チェックだけなら includes が向いている。

どちらも大文字小文字を区別する。
区別したくない場合は、toLowerCase() / toUpperCase() とセットで使う。

ここが重要です。
「場所が欲しいか」「存在だけ知りたいか」を自分に問う癖をつける。
場所が欲しいときに includes を選ぶと物足りないし、
存在だけ知りたいときに indexOf + !== -1 と書くとコードが読みにくくなる。
そこを意識して使い分けられるようになると、“文字列を相手にしたロジック” が一気に書きやすくなります。

小さな練習として、次のような課題を自分で書いてみると良いです。

  1. 文字列 text = "I like JavaScript and TypeScript" を用意する
  2. "JavaScript" が含まれているかを includes で判定する
  3. "Script" の最初の位置を indexOf で求める
  4. "TypeScript" が含まれている場合だけ、その位置から最後までを slice して表示する

この練習をすると、
「検索 → 判定 or 位置取得 → さらに部分取得」という、一連の流れが自分のものになっていきます。

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