JavaScriptで文字列の中に特定のテキストが含まれているかを確認する作業は、プログラミングにおいて最も頻繁に行われる操作の一つです。
ユーザーが入力した情報のバリデーションや、APIから取得したデータのフィルタリング、さらにはログの解析など、その用途は多岐にわたります。
JavaScriptにはこの目的を達成するために複数の手法が用意されており、状況に応じて最適なものを選択することが重要です。
本記事では、モダンな開発で標準となっている手法から、複雑なパターンマッチングに対応する高度な手法まで、具体例を交えて詳しく解説します。
基本となるincludesメソッドによる判定
現在のJavaScript開発において、特定の文字列が含まれているかどうかを判定する最もシンプルで推奨される方法は、includesメソッドを使用することです。
includesメソッドはES2015(ES6)で導入された比較的新しいメソッドであり、直感的なコードを記述できるのが特徴です。
includesメソッドの基本的な使い方
includesメソッドは、対象の文字列に指定したサブ文字列が含まれている場合にtrueを返し、そうでない場合にfalseを返します。
戻り値が真偽値(Boolean)であるため、if文の条件式などでそのまま利用するのに非常に適しています。
// 基本的な使用例
const sentence = "JavaScriptは非常に柔軟なプログラミング言語です。";
const keyword = "柔軟";
if (sentence.includes(keyword)) {
console.log("キーワードが見つかりました。");
}
キーワードが見つかりました。
第2引数を利用した検索開始位置の指定
includesメソッドには、オプションとして第2引数に検索を開始するインデックス番号を指定することができます。
これにより、文字列の特定の範囲内だけで検索を行いたい場合に、余計な計算を省くことが可能になります。
const text = "apple, banana, cherry";
// 10文字目以降から "apple" を探す
const result = text.includes("apple", 10);
console.log(result);
false
上記の例では、10文字目以降には「apple」が存在しないため、falseが返されます。
indexOfメソッドによる従来の手法と使い分け
includesメソッドが登場する前は、indexOfメソッドを使用して文字列の含有判定を行うのが一般的でした。
現在でも、単に「含まれているか」だけでなく「どこにあるか」を知る必要がある場合には、このメソッドが重宝されます。
indexOfメソッドの戻り値と注意点
indexOfメソッドは、指定した文字列が最初に見つかった位置(インデックス)を数値で返します。
文字列が含まれていない場合には -1 を返すという仕様に注意が必要です。
したがって、含まれているかどうかを判定するには、結果が -1 ではないことを確認する必要があります。
const message = "プログラミング学習を楽しもう";
if (message.indexOf("学習") !== -1) {
console.log("「学習」という言葉が含まれています。");
}
「学習」という言葉が含まれています。
なぜ現代でもindexOfが使われるのか
indexOfは、単なる存在チェック以上の情報である「位置」を特定できるため、文字列の切り出し(substring)などと組み合わせて使う際に必須となります。
また、非常に古いブラウザ環境(IEなど)をサポートする必要があるレガシーなプロジェクトでは、includesが使えないためindexOfが採用されます。
しかし、現代的なブラウザ環境やNode.js環境であれば、可読性の観点からincludesメソッドを優先的に使うべきです。
位置を限定した判定:startsWithとendsWith
「含まれているか」という判定の中でも、特に「文字列の先頭」や「末尾」にあるかどうかを確認したい場合があります。
このようなケースでは、includesよりも目的が明確になる専用のメソッドを使用するのがベストプラクティスです。
startsWithメソッドで先頭をチェックする
startsWithメソッドは、文字列が指定された文字列で始まっているかどうかを判定します。
const url = "https://example.com";
if (url.startsWith("https://")) {
console.log("この通信は暗号化されています。");
}
この通信は暗号化されています。
endsWithメソッドで末尾をチェックする
endsWithメソッドは、文字列が指定された文字列で終わっているかどうかを判定します。
ファイルの拡張子を確認する際などに非常によく使われます。
const filename = "document.pdf";
if (filename.endsWith(".pdf")) {
console.log("これはPDFファイルです。");
}
これはPDFファイルです。
正規表現を用いた高度な文字列判定
より複雑な条件、例えば「大文字小文字を区別しない」や「特定のパターン(電話番号やメールアドレスなど)が含まれるか」を判定したい場合は、正規表現(RegExp)を利用します。
JavaScriptで正規表現を使って「含む」を判定するには、主にtest()メソッドを使用します。
testメソッドによるパターンマッチング
正規表現オブジェクトのtest()メソッドは、指定したパターンが文字列内に存在するかどうかを真偽値で返します。
const pattern = /javascript/i; // 'i' フラグは大文字小文字を区別しない設定
const str = "JavaScriptは楽しい";
if (pattern.test(str)) {
console.log("パターンにマッチしました。");
}
パターンにマッチしました。
String.prototype.searchメソッド
文字列側のメソッドであるsearch()も正規表現を受け取ることができます。
これはindexOfと同様に、マッチした位置のインデックスを返し、見つからない場合は -1 を返します。
const text = "Welcome to the world of coding";
const index = text.search(/world/);
console.log(index);
15
大文字と小文字を区別せずに判定する方法
JavaScriptの標準的な文字列メソッド(includesやindexOfなど)は、デフォルトで大文字と小文字を厳密に区別します。
ユーザー検索などで「Apple」と「apple」を同じものとして扱いたい場合、工夫が必要です。
toLowerCaseやtoUpperCaseによる正規化
最も一般的な方法は、比較対象の両方の文字列を一度小文字(または大文字)に変換してから比較することです。
const source = "JavaScript";
const target = "javascript";
// 両方を小文字にして比較する
if (source.toLowerCase().includes(target.toLowerCase())) {
console.log("一致しました(大文字小文字を無視)。");
}
一致しました(大文字小文字を無視)。
正規表現のiフラグを使用する方法
先ほど紹介した正規表現の i フラグを使用すれば、より簡潔に記述できます。
特に検索キーワードが動的に変わる場合は、RegExpコンストラクタを利用して正規表現オブジェクトを生成します。
const input = "JS";
const data = "I love JavaScript";
// 動的な文字列から正規表現を作成
const regex = new RegExp(input, "i");
console.log(regex.test(data));
true
実務で役立つ文字列判定のテクニック
現場では、単一の文字列を判定するだけでなく、複数のキーワードのいずれかを含むかといった、より実戦的な処理が求められます。
複数のキーワードのいずれかを含むか判定する
配列のsomeメソッドとincludesを組み合わせることで、効率的に複数の条件をチェックできます。
const comment = "この商品は素晴らしいですね!";
const forbiddenWords = ["最悪", "詐欺", "ひどい"];
const containsForbidden = forbiddenWords.some(word => comment.includes(word));
if (containsForbidden) {
console.log("不適切な表現が含まれています。");
} else {
console.log("問題ありません。");
}
問題ありません。
空文字列やnull、undefinedの考慮
文字列操作を行う際、対象の変数が null や undefined であるとエラーが発生してプログラムが停止してしまいます。
オプショナルチェイニング(?.)を活用することで、安全に判定を行うことができます。
const userData = null;
// userDataがnullでもエラーにならず、undefinedが返り、結果としてfalse判定になる
if (userData?.includes("admin")) {
console.log("管理者です。");
}
この書き方を採用することで、実行時エラーを防ぎ、堅牢なコードを記述することが可能になります。
パフォーマンス比較とメソッドの選択基準
大量のデータを処理する場合、どのメソッドを使用するかがパフォーマンスに影響を与えることがあります。
一般的には、正規表現よりも組み込みの文字列メソッド(includes, indexOf)の方が高速に動作します。
| メソッド名 | 主な用途 | 戻り値 | 備考 |
|---|---|---|---|
includes() | 存在確認 | Boolean | 最も推奨される標準手法 |
indexOf() | 位置特定 | Number | 古い環境や位置が必要な場合に使用 |
startsWith() | 前方一致 | Boolean | URLやプレフィックスの判定に最適 |
endsWith() | 後方一致 | Boolean | 拡張子の判定などに最適 |
test() (RegExp) | 複雑なパターン | Boolean | 大文字小文字の無視や柔軟な検索 |
判定処理を選択する際は、まず includes で事足りるかを検討し、それでは不十分な場合にのみ他のメソッドへ移行するのが良いでしょう。
シンプルなコードは読みやすく、メンテナンス性も高まるため、オーバーエンジニアリングを避けることが大切です。
まとめ
JavaScriptで文字列が含まれるか判定する方法には、用途に応じて多様な選択肢が存在します。
基本的には直感的で可読性の高い includes メソッドを使用しましょう。
特定の場所を判定したいなら startsWith や endsWith、マッチした位置を知りたいなら indexOf を選択するのが適切です。
そして、大文字小文字を無視した検索や高度なパターンマッチングが必要な場面では、正規表現を使いこなすことで柔軟に対応できます。
これらのメソッドを正しく使い分けることで、バグが少なく効率的なコードを書くことができるようになります。
日々の開発の中で、どの手法がその場面において最も「意図が伝わりやすいか」を意識して選択してみてください。
