indexOf() in JavaScript: finding a position, and watching out for -1

indexOf hands back the position of a value in an array or a string, and -1 when it is missing. That -1 is its most frequent source of bugs.
3 min read
Believemy logo

Before includes existed, every presence check went through indexOf and a comparison against -1. The method stayed, because it answers a different question: not whether the value is there, but where it is.

And that -1, picked as the sign of absence, is worth a stop.


Definition

indexOf hands back the index of the first occurrence of a value, or -1 when it is not there. It works on an Array as well as on a String.

JAVASCRIPT
const languages = ["fr", "en", "es"];

console.log(languages.indexOf("en"));  // 1
console.log(languages.indexOf("de"));  // -1

const path = "/en/courses/formation-javascript";
console.log(path.indexOf("/courses"));  // 3
console.log(path.slice(path.indexOf("formation-")));  // "formation-javascript"

That last line shows the use that still justifies the method: cutting a string at a landmark, which includes cannot do since it only hands back a boolean.


The zero trap

A value found in first position hands back 0, which is a falsy value under the Truthy and falsy rules. Testing the result as a condition therefore flips the logic.

JAVASCRIPT
const roles = ["ROLE_ADMIN", "ROLE_USER"];

if (roles.indexOf("ROLE_ADMIN")) {
  console.log("never printed");  // the index is 0, so the condition is false
}

if (roles.indexOf("ROLE_ADMIN") !== -1) {
  console.log("correct");
}
Good to know

The explicit comparison against -1 is not optional. When presence is all you care about, includes() removes the problem at the root by handing back a boolean directly.


The three search methods

MethodWhat it looks forWhat it hands back
indexOf(value)An exact valueAn index, or -1
lastIndexOf(value)The same, starting from the endAn index, or -1
findIndex(function)The first item passing a testAn index, or -1

The three columns read together: the method, what it takes, what it hands back. The comparison in the first two follows Strict equality (===), so an object is never found by its content. That is what findIndex is for, since it receives a function and compares whatever you want.


Frequently asked questions

Question

Why -1 rather than undefined?

Because the method always hands back a number, and -1 is the only impossible index in an array. The choice dates back to the earliest versions of the language and never changed, for compatibility reasons. Newer methods such as Array.find() do hand back undefined.


Question

How do you find every occurrence?

By restarting the search after each hit, thanks to the second argument that sets the starting point: let i = text.indexOf("a"); while (i !== -1) { positions.push(i); i = text.indexOf("a", i + 1); }. Forgetting the + 1 produces an infinite loop, since the same position is found on every turn.


Question

Why does indexOf miss NaN?

Because it compares with ===, and NaN === NaN is false by definition. An array holding NaN therefore hands back -1. includes() uses a slightly different comparison and does find it, which is one of the rare cases where the two methods disagree.

Related terms

Discover our javaScript glossary

Every word of JavaScript explained simply: keywords, built-in objects, methods, errors and concepts. Clear definitions and examples that actually run, to learn and to troubleshoot.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.