Master JavaScript Array find() and findIndex() methods with real-world examples, output blocks, diagrams, comparisons with filter(), and interview questions. Beginner-friendly guide with detailed explanations.
Introduction
JavaScript arrays store collections of data, and one of the most common tasks is searching for a specific element. The find() method was introduced in ES6 (ES2015) to make this task simple and readable.
Simple Explanation: The find() method returns the first matching element from an array. If no element matches the condition, it returns undefined.
Why find() Matters
Before find(), developers had to write manual loops or use filter()[0] to locate a single element. The find() method provides a clean, declarative approach that:
- Returns the first element satisfying a condition
- Stops immediately after finding a match (short-circuits)
- Returns
undefined if no match exists - Does NOT mutate the original array
The companion method findIndex() works identically but returns the index (position) instead of the element itself, or -1 if not found.
How find() Works — Text Diagram
Here's what happens internally when you call find():
| Array | [ 10, 25, 8, 42, 17 ] |
| Step 1: 10 > 20? | NO → continue |
| Step 2: 25 > 20? | YES → STOP! Return 25 |
| Step 3 | (never reached) |
| Step 4 | (never reached) |
| Step 5 | (never reached) |
| Result | 25 |
Key Insight: The moment find() encounters a truthy return from the callback, it immediately stops and returns that element. This is called short-circuit evaluation.
| Array | [ 10, 25, 8, 42, 17 ] |
| Index | 0 1 2 3 4 |
| Step 1: 10 > 20? | NO |
| Step 2: 25 > 20? | YES → STOP! Return index 1 |
| Result | 1 |
find() vs filter() — Key Difference
| Feature | find() | filter() |
|---|
| Returns | First matching element | All matching elements (array) |
| Return type | Single value or undefined | Always an array (may be empty) |
| Stops early? | ✅ Yes (short-circuits) | ❌ No (checks every element) |
| Use when | You need ONE item | You need ALL matches |
| Performance | Faster for single lookup | Processes entire array |
const scores = [45, 78, 92, 56, 88, 34, 95];
// find() → returns FIRST element > 80
const firstHigh = scores.find(s => s > 80);
console.log(firstHigh);
// filter() → returns ALL elements > 80
const allHigh = scores.filter(s => s > 80);
console.log(allHigh);
Note: find() only returns the first match and stops. filter() checks the entire array and returns all matches.
findIndex() Explanation
findIndex() works exactly like find(), but instead of returning the element, it returns the position (index) where the element was found. If nothing matches, it returns -1.
When to Use findIndex()
- When you need to update an element at its position
- When you need to remove an element using
splice() - When you need to know where something is, not what it is
const fruits = ["apple", "banana", "cherry", "date", "elderberry"];
const index = fruits.findIndex(fruit => fruit.startsWith("c"));
console.log(index);
const notFound = fruits.findIndex(fruit => fruit.startsWith("z"));
console.log(notFound);
Code Examples
Example 1: Find a Number
const numbers = [3, 7, 11, 15, 20, 25];
const firstAboveTen = numbers.find(num => num > 10);
console.log("First above 10:", firstAboveTen);
const firstEven = numbers.find(num => num % 2 === 0);
console.log("First even:", firstEven);
const aboveHundred = numbers.find(num => num > 100);
console.log("Above 100:", aboveHundred);
First above 10: 11
First even: 20
Above 100: undefined
Example 2: Find an Object by Property
const students = [
{ id: 101, name: "Rahul", grade: "A" },
{ id: 102, name: "Priya", grade: "B" },
{ id: 103, name: "Amit", grade: "A" },
{ id: 104, name: "Sneha", grade: "C" }
];
const student = students.find(s => s.id === 103);
console.log("Found student:", student);
const topStudent = students.find(s => s.grade === "A");
console.log("First A-grade:", topStudent.name);
Found student: { id: 103, name: "Amit", grade: "A" }
First A-grade: RahulExample 3: findIndex for Update and Delete
const tasks = [
{ id: 1, title: "Learn HTML", done: true },
{ id: 2, title: "Learn CSS", done: true },
{ id: 3, title: "Learn JavaScript", done: false },
{ id: 4, title: "Learn React", done: false }
];
// Find and update
const idx = tasks.findIndex(t => t.id === 3);
console.log("Index of task 3:", idx);
if (idx !== -1) {
tasks[idx].done = true;
}
console.log("Updated:", tasks[idx]);
// Find and delete
const deleteIdx = tasks.findIndex(t => t.id === 4);
if (deleteIdx !== -1) {
tasks.splice(deleteIdx, 1);
}
console.log("Remaining tasks:", tasks.length);
Index of task 3: 2
Updated: { id: 3, title: "Learn JavaScript", done: true }
Remaining tasks: 3Example 4: Find with Complex Condition
const products = [
{ name: "Laptop", price: 75000, inStock: true, rating: 4.5 },
{ name: "Phone", price: 25000, inStock: false, rating: 4.8 },
{ name: "Tablet", price: 18000, inStock: true, rating: 4.1 },
{ name: "Watch", price: 8000, inStock: true, rating: 4.7 },
{ name: "Headphone", price: 3000, inStock: true, rating: 4.9 }
];
// Find: in stock + under ₹10000 + rating above 4.5
const bestDeal = products.find(p =>
p.inStock && p.price < 10000 && p.rating > 4.5
);
console.log("Best deal:", bestDeal);
// Find: expensive + out of stock
const unavailable = products.find(p =>
!p.inStock && p.price > 20000
);
console.log("Unavailable expensive:", unavailable.name);
Best deal: { name: "Headphone", price: 3000, inStock: true, rating: 4.9 }
Unavailable expensive: PhoneExample 5: Find or Default Pattern
const settings = [
{ key: "theme", value: "dark" },
{ key: "language", value: "hindi" },
{ key: "fontSize", value: "16px" }
];
function getSetting(key, defaultValue) {
const found = settings.find(s => s.key === key);
return found ? found.value : defaultValue;
}
console.log(getSetting("theme", "light"));
console.log(getSetting("language", "english"));
console.log(getSetting("color", "blue"));
console.log(getSetting("notifications", true));
Note: This pattern is useful when you need a default value if the element is not found.
Example 6: findLast() — ES2023 New Method
const transactions = [
{ id: 1, type: "credit", amount: 5000 },
{ id: 2, type: "debit", amount: 2000 },
{ id: 3, type: "credit", amount: 8000 },
{ id: 4, type: "debit", amount: 1500 },
{ id: 5, type: "credit", amount: 3000 }
];
// findLast: searches from END of array
const lastCredit = transactions.findLast(t => t.type === "credit");
console.log("Last credit:", lastCredit);
// findLastIndex: index from end
const lastDebitIdx = transactions.findLastIndex(t => t.type === "debit");
console.log("Last debit index:", lastDebitIdx);
// Compare with find (searches from start)
const firstCredit = transactions.find(t => t.type === "credit");
console.log("First credit:", firstCredit);
Last credit: { id: 5, type: "credit", amount: 3000 }
Last debit index: 3
First credit: { id: 1, type: "credit", amount: 5000 }Example 7: First Non-Repeating Character
function firstUnique(str) {
const charCount = {};
for (const ch of str) {
charCount[ch] = (charCount[ch] || 0) + 1;
}
return str.split("").find(ch => charCount[ch] === 1) || null;
}
console.log(firstUnique("aabbcdef"));
console.log(firstUnique("aabbcc"));
console.log(firstUnique("javascript"));
Example 8: Nested Object Search
const departments = [
{
name: "Engineering",
employees: [
{ id: "E1", name: "Ravi", skill: "React" },
{ id: "E2", name: "Sonia", skill: "Node.js" }
]
},
{
name: "Design",
employees: [
{ id: "D1", name: "Kavya", skill: "Figma" },
{ id: "D2", name: "Arjun", skill: "CSS" }
]
}
];
function findEmployee(empId) {
for (const dept of departments) {
const emp = dept.employees.find(e => e.id === empId);
if (emp) return { ...emp, department: dept.name };
}
return null;
}
console.log(findEmployee("D1"));
console.log(findEmployee("E2"));
console.log(findEmployee("X9"));
{ id: "D1", name: "Kavya", skill: "Figma", department: "Design" }
{ id: "E2", name: "Sonia", skill: "Node.js", department: "Engineering" }
null
Common Mistakes
Mistake 1: Forgetting find() Returns undefined
const nums = [2, 4, 6, 8];
// ❌ WRONG — will throw TypeError
// const result = nums.find(n => n > 10).toFixed(2);
// ✅ CORRECT — check first
const result = nums.find(n => n > 10);
if (result !== undefined) {
console.log(result.toFixed(2));
} else {
console.log("Not found");
}
Mistake 2: Using find() When You Need All Matches
const ages = [15, 22, 18, 30, 12, 25];
// ❌ Only gets first adult
const adult = ages.find(a => a >= 18);
console.log("One adult:", adult);
// ✅ Use filter for ALL adults
const allAdults = ages.filter(a => a >= 18);
console.log("All adults:", allAdults);
One adult: 22
All adults: [22, 18, 30, 25]
Mistake 3: Confusing findIndex() Return with find()
const items = ["pen", "pencil", "eraser"];
// findIndex returns NUMBER, not element
const idx = items.findIndex(i => i === "pencil");
console.log("Index:", idx);
console.log("Element:", items[idx]);
// Returns -1 when not found (NOT undefined)
const missing = items.findIndex(i => i === "ruler");
console.log("Missing index:", missing);
Index: 1
Element: pencil
Missing index: -1
Mistake 4: Mutating Objects Found by find()
const users = [
{ name: "Alice", score: 85 },
{ name: "Bob", score: 72 }
];
// ⚠️ find returns a REFERENCE, not a copy
const alice = users.find(u => u.name === "Alice");
alice.score = 100; // Modifies the ORIGINAL array!
console.log("Original modified:", users[0].score);
// ✅ Spread to create copy if needed
const bobCopy = { ...users.find(u => u.name === "Bob") };
bobCopy.score = 50; // Does NOT affect original
console.log("Original Bob score:", users[1].score);
Original modified: 100
Original Bob score: 72
Mistake 5: Using == Instead of === in Callback
const ids = [1, 2, 3, 4, 5];
const searchId = "3"; // string from user input
// ❌ Loose equality — risky
const found1 = ids.find(id => id == searchId);
console.log("Loose match:", found1);
// ✅ Convert type explicitly
const found2 = ids.find(id => id === Number(searchId));
console.log("Strict match:", found2);
Loose match: 3
Strict match: 3
Key Takeaways
find() returns the first matching element, not an array. If nothing matches, it returns undefined.
findIndex() returns the index of the first match, or -1 if not found.
- Short-circuit behavior — both methods stop iterating the moment a match is found, making them efficient for large arrays.
- Use
find() for single lookups, use filter() when you need all matching elements.
- Always check the return value —
find() can return undefined, which causes TypeErrors if you access properties on it.
find() returns a reference to the original object (not a copy). Modifying it changes the source array.
- ES2023 added
findLast() and findLastIndex() — they search from the end of the array.
- For repeated lookups by ID, convert your array to a
Map for O(1) access instead of O(n) find calls.
findIndex() is essential for update/delete — you need the index to use splice() or direct assignment.
findIndex() over indexOf() — use findIndex() when you need custom conditions or are searching objects.
Interview Questions
Q1: What is the difference between find() and filter()?
Answer: find() returns the first element that matches and stops. filter() returns a new array with ALL matches and processes the entire array.
const arr = [1, 2, 3, 4, 5];
console.log(arr.find(x => x > 2));
console.log(arr.filter(x => x > 2));
Q2: What does find() return if no element matches?
Answer: find() returns undefined. findIndex() returns -1.
const arr = [10, 20, 30];
console.log(arr.find(x => x > 100));
console.log(arr.findIndex(x => x > 100));
Q3: Does find() modify the original array?
Answer: No, but modifying the returned object reference affects the original since objects are passed by reference.
const items = [{ id: 1, active: false }];
const item = items.find(i => i.id === 1);
item.active = true;
console.log(items[0].active);
Q4: Implement find() using a for loop.
function customFind(arr, callback) {
for (let i = 0; i < arr.length; i++) {
if (callback(arr[i], i, arr)) {
return arr[i];
}
}
return undefined;
}
const nums = [5, 12, 8, 130, 44];
console.log(customFind(nums, n => n > 10));
Q5: When should you use findIndex() over indexOf()?
Answer: Use indexOf() for exact primitive values. Use findIndex() when you need a custom condition or are searching objects.
const arr = [10, 20, 30, 40];
console.log(arr.indexOf(30));
console.log(arr.findIndex(x => x > 25));
const users = [{ name: "A" }, { name: "B" }];
console.log(users.findIndex(u => u.name === "B"));
Frequently Asked Questions (FAQ)
FAQ 1: Can find() work on strings?
No, find() is an Array method. For strings, convert to array first with split("").
const str = "hello world";
const firstVowel = str.split("").find(ch => "aeiou".includes(ch));
console.log("First vowel:", firstVowel);
FAQ 2: Is find() supported in all browsers?
Yes, find() and findIndex() work in all modern browsers and Node.js. They do NOT work in Internet Explorer. The newer findLast() (ES2023) requires Chrome 97+, Firefox 104+, Safari 15.4+, Node.js 18+.
FAQ 3: How is find() different from some()?
some() returns a boolean — it tells you IF a match exists. find() returns the actual element.
const prices = [120, 450, 80, 900];
console.log(prices.some(p => p > 500));
console.log(prices.find(p => p > 500));
FAQ 4: What happens if callback modifies the array during find()?
The range of elements is set before the first callback. Elements added after won't be visited. Changed elements use their value at the time the callback visits them.
const arr = [1, 2, 3, 4, 5];
const result = arr.find((elem, index) => {
if (index === 0) arr[3] = 99;
return elem > 50;
});
console.log(result);
FAQ 5: Can I use async/await inside find()?
No. find() expects a synchronous return value. For async searching, use a for...of loop with await.
// ❌ WRONG — find ignores promises
// arr.find(async item => await checkItem(item));
// ✅ CORRECT approach
async function asyncFind(arr, asyncCallback) {
for (const item of arr) {
if (await asyncCallback(item)) return item;
}
return undefined;
}
console.log("Use for...of loop for async find");
Use for...of loop for async find
Quick Reference
// Find first match
const item = arr.find(el => condition);
// Find index of first match
const idx = arr.findIndex(el => condition);
// Find last match (ES2023)
const last = arr.findLast(el => condition);
// Safe find with default
const safe = arr.find(el => condition) ?? defaultValue;
// Find and update
const i = arr.findIndex(el => el.id === targetId);
if (i !== -1) arr[i] = { ...arr[i], updated: true };
// Find and remove
const j = arr.findIndex(el => el.id === targetId);
if (j !== -1) arr.splice(j, 1);
| Method | Match Return | No Match | ES Version |
|---|
find() | First element | undefined | ES2015 |
findIndex() | Index (0+) | -1 | ES2015 |
findLast() | Last element | undefined | ES2023 |
findLastIndex() | Last index | -1 | ES2023 |
Recap: find() returns the first matching element, findIndex() returns its position. Both short-circuit — they stop as soon as a match is found. ES2023 introduced findLast() and findLastIndex() which search from the end.