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.
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.
| Method | Question | Returns |
|---|---|---|
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:
const fruits = ["apple", "banana", "orange"];
console.log(fruits.includes("banana")); // true
console.log(fruits.includes("grape")); // falseYou 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:
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:
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:
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:
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:
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:
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:
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:
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() | |
|---|---|---|---|
| Returns | true / false | Index or -1 | Index or -1 |
| Direction | Forward | Forward | Backward |
| Finds NaN? | Yes | No | No |
| From index? | Yes (2nd arg) | Yes (2nd arg) | Yes (2nd arg) |
| Use case | Existence check | Position lookup | Last 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:
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")); // 3Use 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:
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:
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)); // 0For 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:
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:
const hasApple = fruits.some(f => f.toLowerCase() === "apple");
console.log(hasApple); // trueNow that you can search arrays, learn to unpack values with array destructuring or clean up duplicates with removing duplicates from arrays.
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.
Frequently Asked Questions
What is the difference between includes() and indexOf()?
Can includes() find NaN?
Does indexOf() work with objects?
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.
More in this topic
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.
How to Loop Through Arrays Using JS for Loops Guide
Looping through arrays is the most practical use of JavaScript for loops. Learn how to access each element by index, avoid off-by-one errors, and choose between for, for...of, and forEach.