
The includes method is the simplest way to check if a string contains a particular substring. It returns a boolean—true if the substring exists anywhere within the string, and false otherwise. This method is case-sensitive, so keep that in mind when searching.
Here’s a quick example to demonstrate:
const sentence = "The quick brown fox jumps over the lazy dog";
console.log(sentence.includes("fox")); // true
console.log(sentence.includes("Fox")); // false (case-sensitive)
console.log(sentence.includes("dog")); // true
console.log(sentence.includes("cat")); // false
Because includes returns a boolean, it fits perfectly in conditional statements. For example, you might want to check if a user input contains a forbidden word before processing it further.
function containsForbiddenWord(input) {
const forbidden = "DROP TABLE";
if (input.includes(forbidden)) {
console.log("Warning: input contains forbidden content!");
} else {
console.log("Input looks safe.");
}
}
containsForbiddenWord("SELECT * FROM users;"); // Input looks safe.
containsForbiddenWord("DROP TABLE users;"); // Warning: input contains forbidden content!
Notice that includes can also accept a second argument, which specifies the position in the string to start searching from. That is handy if you want to skip a portion of the string or perform multiple checks.
const text = "Hello world, hello universe";
console.log(text.includes("hello")); // false (case-sensitive)
console.log(text.includes("hello", 13)); // true (starts searching after 'world, ')
Keep in mind that includes is well supported in modern environments but might not be available in very old browsers. For those cases, fallback methods like indexOf are still relevant.
Another subtle but useful feature is that includes works well with Unicode strings, handling emoji and other characters seamlessly.
const emojiString = "I love 🍕 and 🍣";
console.log(emojiString.includes("🍣")); // true
console.log(emojiString.includes("🍔")); // false
So, when you need a clean, readable way to find if a substring exists anywhere inside a string, includes is often your best bet without having to resort to more complex methods or regular expressions. It’s simpler, expressive, and reduces the chances of errors that come from manual index checks.
However, if you want to know where exactly the substring occurs or if you need more control over the matching process, you’ll want to explore alternatives like indexOf or regular expressions. But for a simple true/false test, includes does the job elegantly and with minimal fuss.
One last tip: because includes is case-sensitive, if your search needs to be case-insensitive, you can normalize both strings before the check:
const phrase = "JavaScript is Awesome";
const searchTerm = "awesome";
if (phrase.toLowerCase().includes(searchTerm.toLowerCase())) {
console.log("Found it!");
} else {
console.log("No match.");
}
Transforming both strings to lowercase (or uppercase) is a simple workaround to perform case-insensitive substring detection without jumping into regex territory. But if you find yourself needing pattern matching beyond that, then regex might be the next logical step.
2026 Travel Essentials for Apple Watch Charger,Cruise Vacation Camping Essentials,iPhone Charger,Multi Charging Cable,3 in 2 Charging Docks for iWatch Series 11-2/Ultra,iPhone 17-12,Car
Now retrieving the price.
(as of June 3, 2026 23:09 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)Employing indexOf to locate substrings in strings
The indexOf method predates includes and remains a fundamental tool for substring detection. Unlike includes, which returns a boolean, indexOf returns the numeric position of the first occurrence of a substring within a string, or -1 if the substring is not found.
This behavior makes indexOf especially useful when you need to know where in the string a substring appears, not just whether it exists.
const phrase = "The rain in Spain falls mainly on the plain.";
console.log(phrase.indexOf("Spain")); // 12
console.log(phrase.indexOf("rain")); // 4
console.log(phrase.indexOf("snow")); // -1
Here, the first console log returns 12, indicating that the substring “Spain” starts at the 12th character of phrase. When indexOf returns -1, it signals that the substring cannot be found anywhere in the string.
Because indexOf returns a numeric index, it can be used in conditional statements by checking whether the result is not -1. This has historically been the standard approach before includes became available.
function containsWord(sentence, word) {
if (sentence.indexOf(word) !== -1) {
console.log(The word "${word}" was found.);
} else {
console.log(The word "${word}" was not found.);
}
}
containsWord("Hello world", "world"); // The word "world" was found.
containsWord("Hello world", "mars"); // The word "mars" was not found.
Like includes, indexOf accepts a second argument that specifies the index at which to start the search. This can be used to skip parts of the string or to find subsequent occurrences of a substring after the first.
const text = "banana";
console.log(text.indexOf("an")); // 1 (first occurrence)
console.log(text.indexOf("an", 2)); // 3 (second occurrence)
console.log(text.indexOf("an", 4)); // -1 (no further occurrences)
Using this feature, you can loop through a string to find all occurrences of a substring.
const haystack = "abracadabra";
const needle = "abra";
let position = haystack.indexOf(needle);
while (position !== -1) {
console.log(Found "${needle}" at index ${position});
position = haystack.indexOf(needle, position + 1);
}
This code will output:
Found "abra" at index 0 Found "abra" at index 7
Because indexOf is case-sensitive, you can use the same lowercase normalization trick to perform case-insensitive searches:
const str = "Case Insensitive Search";
const search = "insensitive";
const index = str.toLowerCase().indexOf(search.toLowerCase());
if (index !== -1) {
console.log(Found "${search}" at position ${index});
} else {
console.log("${search}" not found);
}
One subtle but important difference between indexOf and includes is that indexOf can be used to detect substrings at the very start of a string, returning 0. Since 0 is falsy in JavaScript, you need to explicitly check for -1 rather than relying on truthiness.
For example, this common mistake:
const str = "hello world";
if (str.indexOf("hello")) {
console.log("Found it!");
} else {
console.log("Not found.");
}
will actually print “Not found.” because str.indexOf("hello") returns 0, which is falsy. The correct check is:
if (str.indexOf("hello") !== -1) {
console.log("Found it!");
}
This necessity to explicitly compare to -1 is one reason includes was introduced, but indexOf remains powerful when the position is required.
Besides substring detection, indexOf can also be useful for simple parsing tasks. For instance, if you want to extract a substring that follows a specific token, you can locate the token and slice the string accordingly.
const url = "https://example.com/page?query=javascript";
const queryIndex = url.indexOf("query=");
if (queryIndex !== -1) {
const queryValue = url.slice(queryIndex + 6);
console.log(queryValue); // javascript
}
Here, by finding the position of “query=”, you can extract the value after it. This technique can be expanded for simple key-value extraction from strings when you don’t want to use a full parser.
In summary, indexOf is a low-level, versatile method that provides both presence detection and positional information. It’s invaluable when you need to know where a substring occurs or when you want to iterate through multiple occurrences. However, if your needs grow more complex, such as handling patterns or case-insensitive matches without manual normalization, it’s time to consider regular expressions for more expressive substring searches.
Exploring regular expressions for complex substring searches
Regular expressions, often abbreviated as regex, provide a powerful means of searching for patterns within strings. They allow for complex substring searches that go beyond mere presence detection. With regex, you can specify intricate criteria for matching, including character classes, quantifiers, and assertions.
To start using regular expressions in JavaScript, you can create a regex pattern using either a regex literal or the RegExp constructor. Here’s how you can define a simple regex literal:
const regex = /fox/; const sentence = "The quick brown fox jumps over the lazy dog"; console.log(regex.test(sentence)); // true
The test method returns a boolean indicating whether the pattern matches the string. In this case, it returns true because “fox” is present in the sentence.
Regex can also be used to find more complex patterns. For instance, if you want to check for any occurrence of the letters “a”, “b”, or “c”, you can use a character class:
const regex = /[abc]/; const text = "The quick brown dog"; console.log(regex.test(text)); // false
In this example, the regex checks if any of the characters “a”, “b”, or “c” are present in the string. Since none are found, it returns false.
To find all occurrences of a substring that fits a certain pattern, you can use the match method along with the global flag g:
const regex = /[aeiou]/g; const text = "Hello World"; const matches = text.match(regex); console.log(matches); // ["e", "o", "o"]
Here, match returns an array of all vowels found in the string. If no matches are found, it returns null.
Regular expressions also support quantifiers, which allow you to specify how many times a character or group should appear. For example, to match any sequence of one or more digits, you can use the d+ pattern:
const regex = /d+/; const text = "There are 123 apples"; const result = text.match(regex); console.log(result[0]); // "123"
The + quantifier indicates that one or more digits should be matched. This makes regex a powerful tool for parsing numerical data from strings.
For more sophisticated pattern matching, you can use groups and alternation. For example, if you want to match either “cat” or “dog”, you can use the following regex:
const regex = /cat|dog/; const text = "I have a dog"; console.log(regex.test(text)); // true
The | operator acts as a logical OR, which will allow you to match either of the specified strings.
Assertions, such as lookaheads and lookbehinds, enable even more precise matching. A lookahead assertion checks for a pattern only if it is followed by another pattern. For example, to find “foo” only when it is followed by “bar”, you can use:
const regex = /foo(?=bar)/; const text = "foobar"; console.log(regex.test(text)); // true
This regex checks for “foo” only if it’s immediately followed by “bar”, making it a versatile tool for conditional matching.
When using regex, it’s essential to be aware of potential pitfalls, such as performance issues with very complex patterns or the need for escaping special characters. For example, if you want to match a literal period, you need to escape it:
const regex = /./; const text = "This is a sentence."; console.log(regex.test(text)); // true
In this case, the backslash is used to escape the dot, allowing it to be treated as a literal character rather than a wildcard.
Regular expressions are a powerful addition to your toolkit for string manipulation and searching. They offer a level of flexibility and precision that simpler methods cannot achieve, making them invaluable for complex substring searches and data extraction tasks.
