JavaScript Array Includes Indexof and Lastindexof Guide

includes() checks if a value exists. indexOf() finds its first position. lastIndexOf() finds its last. Learn the differences and when to use each method.

6 min read

includes(), indexOf(), and lastIndexOf() are the three built-in methods for searching arrays by value. They do not use callback functions like find() -- they match by strict equality against the value you pass.

MethodQuestionReturns
includes(val)Is this value in the array?true / false
indexOf(val)Where is the first occurrence?Index number or -1
lastIndexOf(val)Where is the last occurrence?Index number or -1

includes() -- Existence Check

includes() returns true if the value exists anywhere in the array, false otherwise, which makes it the clearest choice whenever you only need a yes or no answer:

javascriptjavascript
const fruits = ["apple", "banana", "orange"];
 
console.log(fruits.includes("banana")); // true
console.log(fruits.includes("grape"));  // false

You can provide a second argument to start searching from a specific index, which is useful when you already know an earlier match does not count:

javascriptjavascript
const numbers = [10, 20, 30, 20, 40];
 
console.log(numbers.includes(20));     // true
console.log(numbers.includes(20, 2));  // true (found at index 3)
console.log(numbers.includes(20, 4));  // false (starting after the last 20)

includes() correctly finds NaN, which indexOf() cannot do because of how each method compares values internally. This is one of the few places the two methods disagree on whether a value is present:

javascriptjavascript
const values = [1, NaN, 3];
 
console.log(values.includes(NaN)); // true
console.log(values.indexOf(NaN));  // -1 (surprising!)

This is because includes() uses the SameValueZero algorithm, while indexOf() uses strict equality (===). Since NaN === NaN is false, indexOf() can never find it.

indexOf() -- Find the First Position

indexOf() returns the index of the first occurrence of a value, or -1 if not found:

javascriptjavascript
const colors = ["red", "green", "blue", "green"];
 
console.log(colors.indexOf("green")); // 1 (first "green")
console.log(colors.indexOf("yellow")); // -1 (not found)

Like includes(), you can pass a starting index to skip past matches you have already handled, which is useful when scanning for repeated values one at a time:

javascriptjavascript
const colors = ["red", "green", "blue", "green"];
 
console.log(colors.indexOf("green", 2)); // 3 (skips the first "green")

The indexOf() Boolean Pattern

Before includes() existed, indexOf() was used to check existence. This pattern is still common in older codebases and in code written to support older JavaScript environments:

javascriptjavascript
const fruits = ["apple", "banana", "orange"];
 
if (fruits.indexOf("banana") !== -1) {
  console.log("Found banana");
}

Modern code expresses the same check more directly with includes(), without needing the !== -1 comparison at all, which removes a common source of off-by-one style bugs:

javascriptjavascript
if (fruits.includes("banana")) {
  console.log("Found banana");
}

The !== -1 check is necessary because indexOf() returns -1 on failure and -1 is truthy. Modern code should use includes() for existence checks -- it is clearer and shorter.

lastIndexOf() -- Find the Last Position

lastIndexOf() works like indexOf() but searches from the end of the array backward, so repeated values resolve to their final position instead of their first:

javascriptjavascript
const scores = [85, 92, 78, 92, 88];
 
console.log(scores.indexOf(92));     // 1 (first occurrence)
console.log(scores.lastIndexOf(92)); // 3 (last occurrence)

You can provide a starting index to search backwards from, which limits how far back into the array the search is allowed to look:

javascriptjavascript
const letters = ["a", "b", "c", "b", "a"];
 
console.log(letters.lastIndexOf("b"));    // 3
console.log(letters.lastIndexOf("b", 2)); // 1 (search backwards from index 2)

lastIndexOf() is useful for finding the most recent occurrence of a value in a list that grows over time, like log entries or event sequences.

Comparison Table

includes()indexOf()lastIndexOf()
Returnstrue / falseIndex or -1Index or -1
DirectionForwardForwardBackward
Finds NaN?YesNoNo
From index?Yes (2nd arg)Yes (2nd arg)Yes (2nd arg)
Use caseExistence checkPosition lookupLast occurrence

When to Use Each

Each method answers a different question about the same array, as this side-by-side example on a list of project phases shows:

javascriptjavascript
const tasks = ["setup", "development", "review", "development", "deploy"];
 
// "Is development in the list?"
console.log(tasks.includes("development")); // true
 
// "Where does development first appear?"
console.log(tasks.indexOf("development")); // 1
 
// "Where was the last development phase?"
console.log(tasks.lastIndexOf("development")); // 3

Use includes() for conditionals and guards. Use indexOf() when you need the position to slice, splice, or replace. Use lastIndexOf() when order matters and you want the most recent match.

Common Mistakes

Using indexOf() for existence checks without comparing to -1. Since -1 is a truthy value in JavaScript, treating the raw return value as a boolean produces the opposite of what you intended:

javascriptjavascript
const items = ["apple", "banana"];
 
// Bug: indexOf returns -1, which is truthy
if (items.indexOf("grape")) {
  console.log("Found"); // This runs! (-1 is truthy)
}
 
// Correct: explicitly check for -1
if (items.indexOf("grape") !== -1) {
  console.log("Found");
}

Expecting indexOf() to find objects by property. Passing a freshly created object literal never matches, even if an equal-looking object already exists in the array:

javascriptjavascript
const users = [{ id: 1 }, { id: 2 }];
 
// Wrong: indexOf uses ===, objects are compared by reference
console.log(users.indexOf({ id: 1 })); // -1
 
// Right: use findIndex() for object matching by property
console.log(users.findIndex(u => u.id === 1)); // 0

For finding objects by condition, use findIndex() with a callback instead of indexOf().

Forgetting that includes() is case-sensitive. A search term that differs only in capitalization from every array element will not match:

javascriptjavascript
const fruits = ["Apple", "banana", "Orange"];
 
console.log(fruits.includes("apple")); // false (case mismatch)

includes() uses strict equality with no case normalization built in. For case-insensitive checks, convert both sides to the same case or use some() with a custom comparison:

javascriptjavascript
const hasApple = fruits.some(f => f.toLowerCase() === "apple");
console.log(hasApple); // true

Now that you can search arrays, learn to unpack values with array destructuring or clean up duplicates with removing duplicates from arrays.

Rune AI

Rune AI

Key Insights

  • includes(value) returns true if the value exists in the array, false otherwise.
  • indexOf(value) returns the first index of the value, or -1 if not found.
  • lastIndexOf(value) searches from the end and returns the last occurrence index.
  • includes() correctly finds NaN. indexOf() cannot because NaN !== NaN.
  • All three methods use strict equality (===) for comparison, except includes() with NaN.
RunePowered by Rune AI

Frequently Asked Questions

What is the difference between includes() and indexOf()?

includes() returns a boolean (true or false). indexOf() returns the index position (a number) or -1 if not found. Use includes() when you only need to know if a value exists. Use indexOf() when you need to know where it is.

Can includes() find NaN?

Yes. includes() uses the SameValueZero algorithm, which correctly identifies NaN. indexOf() uses strict equality (===), which cannot find NaN because NaN !== NaN.

Does indexOf() work with objects?

indexOf() uses strict equality (===), so it can only find an object if you pass the exact same object reference. It will not find an object with the same properties but a different reference.

Conclusion

includes(), indexOf(), and lastIndexOf() are the three fundamental search methods for arrays. includes() answers 'is it there?' indexOf() answers 'where is it first?' lastIndexOf() answers 'where is it last?' The key distinction is that includes() handles NaN correctly while indexOf() does not. Choose includes() for existence checks and indexOf() when you need the position.