JavaScript Tips | 文字列操作:文字列に指定文字が含まれるか判定する

JavaScript JavaScript
スポンサーリンク
スポンサーリンク

業務・実務で使える JavaScript ユーティリティ:文字列に指定文字が含まれるか判定する方法

JavaScriptで「文字列に指定した文字や単語が含まれているか」を判定する処理は、業務・実務で非常によく使います。検索キーワードのチェック、URL判定、入力値バリデーション、ログ解析、ファイル名判定、権限文字列の確認、簡易フィルタリングなど、さまざまな場面で登場します。

一見すると単純な処理に見えますが、実務では「大文字小文字を区別するのか」「部分一致でよいのか」「空文字をどう扱うのか」「null や undefined が来たらどうするのか」「ユーザー入力をそのまま信用してよいのか」といった点を考える必要があります。

つまり、文字列に指定文字が含まれるかどうかの判定は、単なる小さなテクニックではありません。入力データを安全かつ意図どおりに扱うための、実務的にとても重要な基礎処理です。

まず理解したい:何をもって「含まれる」と判断するのか

初心者の方が最初に押さえたいのは、「含まれる」という言葉が意外と曖昧だということです。たとえば、次のようなケースを考えてみます。

  • "JavaScript" に "Script" は含まれる
  • "JavaScript" に "script" は、大文字小文字を区別すると含まれない
  • "error_log.txt" に ".txt" は含まれる
  • "administrator" に "admin" は含まれる
  • "cat" に "c" は含まれる

このように、「含まれる」は基本的に部分一致です。そのため、業務では「その判定で本当に十分か」を考える必要があります。たとえば権限判定や単語判定では、ただ部分一致するだけでは誤判定になることがあります。

まずはここをしっかり理解してください。文字列に含まれるかを判定する処理は便利ですが、用途によっては「完全一致」「前方一致」「後方一致」「単語単位一致」のほうが適切なこともあります。

もっとも基本的な方法:includes()

JavaScriptで文字列に指定文字が含まれるかを判定する基本は、includes() メソッドです。これは最初に覚えるべき最重要の方法です。

// 文字列に指定した文字列が含まれるかを判定する基本例
const text = "JavaScript utility";
const result = text.includes("Script");

console.log(result); // true
JavaScript

includes() は、含まれていれば true、含まれていなければ false を返します。返り値が真偽値なので、if 文と非常に相性がよいです。

// if文で使う例
const fileName = "report.pdf";

if (fileName.includes(".pdf")) {
  console.log("PDFファイルです");
} else {
  console.log("PDFファイルではありません");
}
JavaScript

初心者の方はまず、この includes() を自然に使えるようになることが大切です。実務でも、単純な部分一致判定の多くはこれで十分対応できます。

ステップバイステップで考える

ここからは、実務で文字列に指定文字が含まれるかを判定するときの考え方を、順番に整理していきます。

ステップ1:まずは素直に判定したい文字列を決める

最初にやるべきことは、「何の中に」「何が含まれるか」をはっきりさせることです。たとえば次のような形です。

  • 対象文字列:"error: invalid token"
  • 探したい文字列:"error"
// 基本の判定
const text = "error: invalid token";
const keyword = "error";

console.log(text.includes(keyword)); // true
JavaScript

これはとても単純ですが、実務では「対象文字列」と「探したい文字列」を最初に明確に区別することが大切です。変数名を曖昧にすると、ロジックが読みにくくなります。

ステップ2:大文字小文字を区別するか決める

includes() は、大文字小文字を区別します。ここは初心者がつまずきやすい重要ポイントです。

// 大文字小文字は区別される
const text = "JavaScript";

console.log(text.includes("Script")); // true
console.log(text.includes("script")); // false
JavaScript

業務では、大文字小文字を区別したいケースと、区別したくないケースがあります。たとえばメールアドレスや検索キーワード、URLの一部などでは、区別しないほうが扱いやすいことがあります。

大文字小文字を無視して判定したいなら、両方を同じ形にそろえてから判定します。

// 大文字小文字を無視して判定する例
const text = "JavaScript";
const keyword = "script";

const result = text.toLowerCase().includes(keyword.toLowerCase());

console.log(result); // true
JavaScript

この考え方は実務で非常によく使います。比較前に正規化する、という発想です。単純なようですが、バグを防ぐうえでかなり重要です。

ステップ3:空文字をどう扱うか考える

ここは見落とされやすいですが、とても大切です。JavaScriptでは、空文字 "" に対する includes() の結果は true になります。

// 空文字を探すと true になる
const text = "hello";

console.log(text.includes("")); // true
JavaScript

仕様としては正しいのですが、業務ロジックでは意図しないことがあります。たとえば検索キーワードが空のときに、すべて一致扱いになると困ることがあります。

そのため、実務向けには「探したい文字列が空なら false にする」といったルールを明示的に入れることが多いです。

// 空文字を無効として扱う例
function containsText(text, keyword) {
  // keyword が空文字なら false を返す
  if (keyword === "") {
    return false;
  }

  return text.includes(keyword);
}

console.log(containsText("hello", "")); // false
JavaScript

このような小さな仕様の差が、実務ではとても重要です。「言語仕様としてどうか」と「業務要件としてどうすべきか」は分けて考える必要があります。

ステップ4:null や undefined に備える

実務で文字列処理を書くときは、入力が常にきれいな文字列だと思わないことが大切です。null や undefined に対して、そのまま includes() を呼ぶとエラーになります。

// これはエラーになる例
const text = null;
console.log(text.includes("a")); // TypeError
JavaScript

そのため、防御的に書くなら、先に入力チェックを入れます。

// null / undefined に安全な判定関数
function safeIncludes(text, keyword) {
  // text または keyword が null / undefined なら false を返す
  if (text == null || keyword == null) {
    return false;
  }

  return String(text).includes(String(keyword));
}

console.log(safeIncludes(null, "a"));       // false
console.log(safeIncludes("hello", null));   // false
console.log(safeIncludes("hello", "ell"));  // true
JavaScript

ここで String() を使っているのは、数値などが来ても文字列として扱えるようにするためです。このあたりは実務で特に重要です。関数が「文字列だけを受け取る前提」なのか、「ある程度入力の揺れを吸収する前提」なのかを決めておく必要があります。

indexOf() との違いも理解する

古いコードや既存システムでは、includes() の代わりに indexOf() が使われていることがあります。これも知っておくと実務で役立ちます。

// indexOf() を使う例
const text = "JavaScript";
const result = text.indexOf("Script");

console.log(result); // 4
JavaScript

indexOf() は、見つかった位置を数値で返します。見つからなければ -1 を返します。

// indexOf() で含まれるかを判定する例
const text = "JavaScript";

if (text.indexOf("Script") !== -1) {
  console.log("含まれています");
}
JavaScript

ただし、単純に含まれるかどうかだけを判定したいなら、現在は includes() のほうが読みやすいです。初心者の方はまず includes() を中心に覚え、既存コードを読むときのために indexOf() も知っておく、という理解で十分です。

実務で重要な注意点

部分一致で誤判定しないかを考える

ここはかなり重要です。includes() は部分一致なので、意図しない一致が起こることがあります。

// 部分一致による誤判定の例
const role = "administrator";

console.log(role.includes("admin")); // true
JavaScript

この結果自体は正しいですが、もし「権限名が admin かどうか」を判定したいなら不適切です。これは完全一致で判定すべき場面です。

// 完全一致にするべき例
const role = "administrator";

console.log(role === "admin"); // false
JavaScript

つまり、文字列が含まれるか判定するときは、まず「本当に部分一致でよいのか」を確認する必要があります。権限、ステータス、固定コード、拡張子判定などでは、誤判定が業務上の不具合につながることがあります。

セキュリティ判定を単純な文字列包含だけに頼らない

情報セキュリティの観点では、ここは強く意識したいポイントです。たとえば危険な文字列を含むかどうかだけで入力を安全と判断するのは不十分です。

単純な includes() は便利ですが、入力検証、認可判定、危険文字の検出などで万能ではありません。なぜなら、表記ゆれ、大文字小文字、エンコード、前後の余分な文字、別の文脈での一致などにより、すり抜けや誤検知が起こりうるからです。

たとえば次のような場面では特に注意が必要です。

  • 管理者権限を表す文字列の判定
  • URLの許可ドメインチェック
  • 危険語句のブラックリスト検査
  • SQLやHTML断片の簡易検知

こうした場面では、単純な部分一致ではなく、構造的な検証、厳密な比較、専用のバリデーション設計が必要です。小さなユーティリティだからこそ、用途を超えて過信しない姿勢が重要です。

検索対象が配列なのか文字列なのかを混同しない

初心者の方は、文字列の includes() と配列の includes() を混同しやすいです。名前は同じですが、対象が異なります。

// 文字列の includes()
console.log("apple banana".includes("apple")); // true

// 配列の includes()
console.log(["apple", "banana"].includes("apple")); // true
JavaScript

文字列では部分一致ですが、配列では要素一致です。この違いはとても大切です。

  • "apple banana".includes("app") は true
  • ["apple", "banana"].includes("app") は false

同じ名前だから同じ感覚で使えると思い込まないことが大切です。

実務向けの完成版テンプレート

ここまでの注意点を踏まえて、業務・実務で使いやすい安全寄りのテンプレートを紹介します。これは、null 安全、空文字対策、大文字小文字の切り替え対応を備えた例です。

/**
 * 文字列に指定した文字列が含まれるか判定する
 *
 * 仕様:
 * - text または keyword が null / undefined の場合は false
 * - keyword が空文字の場合は false
 * - ignoreCase が true の場合は大文字小文字を無視する
 */
function containsText(text, keyword, ignoreCase = false) {
  // text または keyword が null / undefined なら false
  if (text == null || keyword == null) {
    return false;
  }

  // 文字列に変換する
  const source = String(text);
  const target = String(keyword);

  // 空文字の検索は無効とする
  if (target === "") {
    return false;
  }

  // 大文字小文字を無視したい場合
  if (ignoreCase) {
    return source.toLowerCase().includes(target.toLowerCase());
  }

  // 通常の部分一致判定
  return source.includes(target);
}

// 使用例
console.log(containsText("JavaScript", "Script"));        // true
console.log(containsText("JavaScript", "script"));        // false
console.log(containsText("JavaScript", "script", true));  // true
console.log(containsText(null, "a"));                     // false
console.log(containsText("hello", ""));                   // false
JavaScript

このテンプレートのよい点は、「何をどう扱うか」が明確にコードへ表れていることです。実務では、短いコードよりも、仕様が読み取れるコードのほうが価値があります。

例題で理解を深める

例題1:ファイル拡張子の確認

// PDFファイルかどうかを確認する例
const fileName = "manual.pdf";

if (containsText(fileName, ".pdf")) {
  console.log("PDFファイルです");
}
JavaScript

ただし、拡張子判定では単なる包含より、末尾一致のほうが厳密です。たとえば "pdf_backup.txt" にも ".pdf" に近い文字列が紛れる可能性があります。用途によっては endsWith() のほうが適切です。

例題2:エラーメッセージの簡易判定

// エラー文字列を含むか判定する例
const logMessage = "Error: Invalid token";

if (containsText(logMessage, "error", true)) {
  console.log("エラー関連のログです");
}
JavaScript

ログ解析では大文字小文字が揺れることが多いため、無視して判定するのが便利です。

例題3:検索キーワードの一致確認

// 検索ワードが商品名に含まれるかを判定する例
const productName = "Wireless Mouse";
const keyword = "mouse";

if (containsText(productName, keyword, true)) {
  console.log("検索結果に含めます");
}
JavaScript

このようなケースでは、部分一致判定が自然に使えます。ただし本格的な検索では、前処理や正規化をさらに加えることが多いです。

テストで挙動を確認する

ユーティリティ関数は、思ったより細かい仕様差でバグが出ます。そのため、代表的なケースをまとめて確認することが大切です。

// 代表的なテストケース
const testCases = [
  ["JavaScript", "Script", false, true],
  ["JavaScript", "script", false, false],
  ["JavaScript", "script", true, true],
  ["hello", "", false, false],
  [null, "a", false, false],
  ["error_log.txt", ".txt", false, true],
  ["administrator", "admin", false, true]
];

for (const [text, keyword, ignoreCase, expected] of testCases) {
  const actual = containsText(text, keyword, ignoreCase);

  console.log({
    text,
    keyword,
    ignoreCase,
    expected,
    actual,
    pass: actual === expected
  });
}
JavaScript

このようにテストケースを並べると、「空文字はどうするか」「大文字小文字はどうするか」「null はどうするか」といった仕様がはっきり見えるようになります。実務では、こうした明文化が非常に重要です。

初心者がつまずきやすいポイント

includes() と完全一致を混同する

もっとも多いのはここです。includes() は部分一致です。値そのものが一致しているかを調べたいなら、=== を使う必要があります。

大文字小文字の違いを見落とす

見た目では同じように見えても、JavaScriptは文字列比較で大文字小文字を区別します。検索や入力チェックでは、比較前に toLowerCase() などでそろえるべきかを考えることが大切です。

空文字の挙動を知らない

includes("") が true になることは、初心者にとって意外なポイントです。業務ロジックではこのままだと困ることがあるため、明示的にルールを決める必要があります。

入力値を信用してしまう

これは小さな処理でも非常に重要です。業務コードでは、入力が null、undefined、数値、空文字、余分な空白付き文字列など、いろいろな形で来る可能性があります。ユーティリティ関数こそ、防御的に書く習慣を身につける練習に向いています。

より実務的に考えるための確認ポイント

実装前に、次の点を確認しておくと失敗しにくくなります。

  • 部分一致でよいのか、それとも完全一致が必要か
  • 大文字小文字を区別するか
  • 空文字を有効な検索語として扱うか
  • null や undefined はどう扱うか
  • 比較前に前後空白を削除する必要があるか
  • セキュリティ判断に使ってよい処理か、それとも別の厳密な検証が必要か

この確認を先にしておくと、「動くけれど危ないコード」ではなく、「要件に合っていて壊れにくいコード」に近づけます。

すぐ使える最終テンプレート

最後に、そのまま業務で流用しやすい形のテンプレートをまとめます。

/**
 * 文字列に指定した文字列が含まれるかを判定する
 *
 * @param {any} text - 判定対象の値
 * @param {any} keyword - 探したい文字列
 * @param {boolean} ignoreCase - true の場合は大文字小文字を無視する
 * @returns {boolean} 含まれていれば true、そうでなければ false
 */
function containsText(text, keyword, ignoreCase = false) {
  // null / undefined は false にする
  if (text == null || keyword == null) {
    return false;
  }

  // 文字列へ変換する
  const source = String(text);
  const target = String(keyword);

  // 空文字は無効とする
  if (target === "") {
    return false;
  }

  // 大文字小文字を無視する場合
  if (ignoreCase) {
    return source.toLowerCase().includes(target.toLowerCase());
  }

  // 通常の部分一致判定
  return source.includes(target);
}

// 使用例
console.log(containsText("JavaScript utility", "Script"));        // true
console.log(containsText("JavaScript utility", "script"));        // false
console.log(containsText("JavaScript utility", "script", true));  // true
console.log(containsText("report.pdf", ".pdf"));                  // true
console.log(containsText(null, "pdf"));                           // false
console.log(containsText("hello", ""));                           // false
JavaScript

まとめ

JavaScriptで文字列に指定文字が含まれるかを判定する処理は、includes() を中心に書けます。しかし実務では、単に使えるだけでは不十分です。大文字小文字、空文字、null、部分一致による誤判定など、考えるべきポイントが多くあります。

特に大切なのは次の点です。

  • includes() は部分一致であることを理解すること
  • 大文字小文字を区別するか先に決めること
  • 空文字や null をどう扱うか明確にすること
  • 権限判定や安全性判断を単純な部分一致だけに頼らないこと
  • テストケースを用意して仕様を確認すること

初心者の方は、まず includes() の基本を身につけ、そのうえで「入力をそのまま信用しない」「用途に応じて比較方法を選ぶ」という実務的な視点を持つことが重要です。こうした小さなユーティリティの品質が、アプリ全体の読みやすさ、壊れにくさ、安全性につながっていきます。

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