How to check whether a string contains a substring in JavaScript?
Categories:
Mastering Substring Checks in JavaScript: A Comprehensive Guide

Learn various methods to efficiently determine if a string contains a specific substring in JavaScript, from modern built-in functions to traditional approaches.
Checking if a string contains a substring is a fundamental operation in JavaScript programming. Whether you're validating user input, parsing data, or implementing search functionality, knowing the right method can significantly impact your code's readability and performance. This article explores several common and efficient ways to perform substring checks in JavaScript, detailing their usage, advantages, and browser compatibility.
The Modern Approach: String.prototype.includes()
Introduced in ECMAScript 6 (ES6), the includes()
method is the most straightforward and readable way to check for a substring. It returns true
if the string contains the specified substring, and false
otherwise. It's case-sensitive and can optionally take a second argument to specify the position at which to begin searching.
const mainString = "Hello, world!";
const substring1 = "world";
const substring2 = "World";
const substring3 = "planet";
console.log(mainString.includes(substring1)); // true
console.log(mainString.includes(substring2)); // false (case-sensitive)
console.log(mainString.includes(substring3)); // false
// Search starting from a specific index
const sentence = "The quick brown fox jumps over the lazy dog.";
console.log(sentence.includes("fox", 10)); // true (search starts at index 10)
console.log(sentence.includes("fox", 20)); // false (search starts after "fox")
Using includes()
for basic and indexed substring checks.
includes()
, convert both the main string and the substring to the same case (e.g., toLowerCase()
or toUpperCase()
) before comparison.Traditional Methods: String.prototype.indexOf()
Before includes()
, indexOf()
was the go-to method. It returns the index of the first occurrence of the specified substring within the calling string, or -1
if the substring is not found. This means a return value other than -1
indicates the presence of the substring. Like includes()
, it's case-sensitive and supports an optional starting index.
const text = "JavaScript is fun.";
const search1 = "Script";
const search2 = "script";
const search3 = "Python";
console.log(text.indexOf(search1) !== -1); // true
console.log(text.indexOf(search2) !== -1); // false (case-sensitive)
console.log(text.indexOf(search3) !== -1); // false
// Search starting from a specific index
const phrase = "apple banana apple";
console.log(phrase.indexOf("apple", 1)); // 13 (finds the second 'apple')
Using indexOf()
to check for substring presence.
indexOf()
is perfectly valid, includes()
is generally preferred for simple presence checks due to its clearer semantic meaning and better readability.Advanced Pattern Matching: Regular Expressions with String.prototype.match()
or RegExp.prototype.test()
For more complex substring checks, such as finding patterns, ignoring case, or searching for multiple alternatives, regular expressions are invaluable. JavaScript provides String.prototype.match()
and RegExp.prototype.test()
for this purpose.
RegExp.prototype.test()
is often the most efficient for simply checking if a pattern exists, as it returns a boolean. String.prototype.match()
returns an array of matches or null
if no match is found, which is useful when you need to extract the matches themselves.
const data = "The quick brown fox.";
// Using RegExp.prototype.test() for boolean check
const regex1 = /quick/;
console.log(regex1.test(data)); // true
const regex2 = /Quick/i; // 'i' flag for case-insensitive
console.log(regex2.test(data)); // true
const regex3 = /zebra/;
console.log(regex3.test(data)); // false
// Using String.prototype.match() to get matches or null
console.log(data.match(/brown/)); // ["brown", index: 10, input: "The quick brown fox.", groups: undefined]
console.log(data.match(/Brown/i)); // ["brown", index: 10, input: "The quick brown fox.", groups: undefined]
console.log(data.match(/cat/)); // null
Using regular expressions for flexible substring matching.
flowchart TD A[Start: Check Substring] --> B{Is it a simple, exact match?} B -- Yes --> C[Use `string.includes(substring)`] B -- No, need index --> D[Use `string.indexOf(substring) !== -1`] B -- No, complex pattern/case-insensitive --> E{Need to extract matches?} E -- Yes --> F[Use `string.match(/pattern/flags)`] E -- No, just boolean --> G[Use `/pattern/flags.test(string)`] C --> H[End] D --> H[End] F --> H[End] G --> H[End]
Decision flow for choosing the right substring check method.