
String.startsWith(), endsWith(), and includes() in JavaScript

There is a particular kind of JavaScript code that works perfectly well and still feels older than it needs to be.
String checks built around indexOf() are a good example.
For years, we wrote things like:
if (url.indexOf('/admin') === 0) { // ...}or:
if (filename.indexOf('.jpg') !== -1) { // ...}That is not wrong, but it forces you to translate low‑level numeric conditions back into the string question you were actually asking.
ES6 gave us three methods that make this much clearer:
startsWith()endsWith()includes()
startsWith() says exactly what it means
If we want to know whether a string begins with a particular substring, the method is wonderfully direct:
const path = '/admin/settings';const isAdminRoute = path.startsWith('/admin');That reads almost like English.
Compared with:
const isAdminRoute = path.indexOf('/admin') === 0;the intent is much easier to spot immediately.
endsWith() is just as straightforward
This is useful for file extensions, route fragments, suffix‑based naming, and plenty more:
const filename = 'photo.jpg';const isJpeg = filename.endsWith('.jpg');Again, the code says what it is doing without the reader needing to remember how to interpret a number from indexOf().
includes() answers the general contains question
When the question is simply "does this string contain that substring anywhere?", includes() is the cleanest option:
const message = 'Your order has been dispatched';const mentionsDispatch = message.includes('dispatch');That replaces the old pattern:
const mentionsDispatch = message.indexOf('dispatch') !== -1;It is a small improvement in syntax, but quite a big improvement in readability.
Why Readability Matters Here
These checks appear everywhere:
- URL handling
- form validation
- search filtering
- feature toggles
- file‑type checks
- little content rules in UI code
Because they are so common, making them easier to scan pays off quickly.
Good APIs are not only about capability. They are also about reducing the amount of mental decoding the reader has to do.
These Methods are Case‑Sensitive
This is one of the first practical caveats.
const name = 'JavaScript';console.log(name.includes('script'));That returns false because 'script' and 'Script' are not the same sequence of characters.
If we want case‑insensitive matching, we need to normalise:
const containsScript = name.toLowerCase().includes('script');That is not a flaw in the methods. It is just how exact string matching works.
startsWith() and includes() are not regular expressions
Another small but important limitation: these methods work with strings, not regex patterns.
If we need pattern matching, optional groups, or more advanced rules, regular expressions are still the right tool.
That said, developers often reach for a regex when all they really need is:
- a simple prefix check
- a simple suffix check
- a straightforward substring test
In those cases, the dedicated methods are usually the cleaner choice.
The Optional Position Arguments are Worth Knowing
startsWith() can start checking from a later position:
const value = '---error';console.log(value.startsWith('error', 3));That returns true.
includes() also accepts a starting position:
const text = 'banana';console.log(text.includes('na', 3));That starts searching at index 3.
endsWith() has its own slightly different optional length parameter, which lets you treat the string as though it ended earlier:
const filename = 'report.txt.backup';console.log(filename.endsWith('.txt', 10));That checks the string as though it were only ten characters long.
You will not use those extra parameters every day, but they are handy when you need them.
A Few Realistic Examples
Route handling:
const isArticleRoute = window.location.pathname.startsWith('/articles/');Basic search filtering:
const matchesSearch = title.toLowerCase().includes(query.toLowerCase());File extension check:
const isSvg = filename.endsWith('.svg');These are all ordinary front‑end tasks, and each one reads more clearly with the dedicated string methods than with numeric index comparisons.
Cleaner Syntax Also Reduces Bugs
Code like:
if (filename.indexOf('.jpg')) { // ...}is a classic source of mistakes because indexOf() returning 0 is falsy, while returning ‑1 is truthy enough to confuse people who are not thinking carefully.
The newer methods sidestep that entire class of bug because they return booleans directly.
That alone makes them safer for beginners and easier to review in larger codebases.
They are Not Only Nicer, They are More Honest
indexOf() answers the question "where is this substring?"
Sometimes that is what we genuinely need.
But quite often the real question is one of these:
- does it start with this?
- does it end with this?
- does it contain this?
When the API matches the question directly, the code becomes easier to trust.
The Right Method is Usually Obvious Once You Name the Question Properly
If the logic feels slightly awkward, that is often a clue that the method does not match the intention.
If you want a boolean answer about containment or position at the edges of a string, startsWith(), endsWith(), and includes() are usually the right tools. Save indexOf() for the moments when the actual numeric position matters.
That is the real win here. ES6 did not introduce some brand‑new capability. It gave us a better vocabulary for something we already did constantly.
And better vocabulary nearly always leads to better code.
Related Articles

Understanding Phantom window.resize Events in iOS. Understanding Phantom

Array.includes() vs. indexOf() in JavaScript. Array.includes()vs.indexOf()in JavaScript
10 Essential SEO Tips for Front‑End Developers. 10 Essential SEO Tips for Front‑End Developers

Leveraging .then() in Modern JavaScript. Leveraging
.then()in Modern JavaScript
Why querySelector Returns null in JavaScript. Why
querySelectorReturnsnullin JavaScript
Specificity in CSS. Specificity in CSS
Web Development and the Environment. Web Development and the Environment

Promises in JavaScript: An Introduction. Promises in JavaScript: An Introduction
Where to Find Jobs in Web Development. Where to Find Jobs in Web Development

Can I Learn Front‑End Development in 2 Months? Can I Learn Front‑End Development in 2 Months?

Parent Selectors in CSS and Sass. Parent Selectors in CSS and Sass

JavaScript Array Manipulation: slice() vs. splice(). JavaScript Array Manipulation:
slice()vs.splice()