Why interviewers ask this
Array methods look like a memorization topic, "here are twelve methods, know what each does," but the questions that actually separate candidates are about correctness traps: a sort that silently does the wrong thing, a mutation that corrupts data somewhere the candidate didn't expect, a find that returns undefined instead of throwing an error. This guide is built around those traps specifically.
The first four questions get full treatment: working code, the common mistake, and the explanation. The remaining six are tighter: one working example and the insight it tests.
How interviewers read an array-methods answer
| Layer | What a weaker answer does | What a stronger answer does |
| Mutation awareness | Doesn't know or mention whether a method changes the original array | States upfront whether a method mutates, and chooses accordingly based on whether the original needs to stay intact |
| Correctness | Uses sort() without a comparator and gets unexpected results on numbers | Always supplies a comparator for numeric or custom sorting |
| Method selection | Reaches for filter or a manual loop when find, some, or reduce would be more direct | Picks the method whose return type and behavior actually match what the problem needs |
| Communication | Chains methods without narrating what each step produces | Explains what shape the data is in after each step of a chain |
1How do you use reduce to group an array of objects by a property?
const people = [
{ name: "Zoe", department: "eng" },
{ name: "Amit", department: "sales" },
{ name: "Lin", department: "eng" }
];
const grouped = people.reduce((acc, person) => {
(acc[person.department] ||= []).push(person);
return acc;
}, {});
console.log(grouped);
// { eng: [{name: 'Zoe', ...}, {name: 'Lin', ...}], sales: [{name: 'Amit', ...}] }reduce builds up a single accumulator (acc) across every element, here an object keyed by department. The naive alternative uses a manual loop with an explicit existence check:
const grouped2 = {};
for (const person of people) {
if (!grouped2[person.department]) {
grouped2[person.department] = [];
}
grouped2[person.department].push(person);
}Both produce the same result. The difference is that reduce expresses the same logic as a single expression rather than a multi-line imperative loop, which most interviewers read as a stronger command of the language's functional tools.
Evaluates: whether the candidate sees reduce as more than a summing tool. Grouping, counting, and flattening are all reduce patterns, and recognizing that generalizes far better than memorizing "reduce adds numbers."
2How do you sort an array of numbers correctly, and what goes wrong without a comparator?
const nums = [10, 1, 21, 2];
console.log(nums.sort());
// [1, 10, 2, 21] -- wrong! sorted as strings, not numbers
console.log(nums.sort((a, b) => a - b));
// [1, 2, 10, 21] -- correctWithout a comparator function, sort() converts every element to a string and compares them lexicographically, so "10" sorts before "2" because "1" comes before "2" character by character. Supplying (a, b) => a - b tells sort to compare numerically instead.
There's a second trap in this same example: sort() mutates the original array in place.
const original = [3, 1, 2];
const sorted = original.sort();
console.log(original); // [1, 2, 3] -- the "original" array changed tooEvaluates: two things at once, whether the candidate knows to always supply a comparator for numeric sorting, and whether they know sort() mutates the array it's called on rather than returning a new one. Both are extremely common sources of real bugs, not just interview trivia.
3What's the difference between find, findIndex, and filter?
const users = [
{ id: 1, name: "Zoe" },
{ id: 2, name: "Amit" },
{ id: 3, name: "Lin" }
];
console.log(users.find(u => u.id === 2)); // { id: 2, name: 'Amit' }
console.log(users.findIndex(u => u.id === 2)); // 1
console.log(users.filter(u => u.id === 2)); // [{ id: 2, name: 'Amit' }]
console.log(users.find(u => u.id === 99)); // undefined
console.log(users.filter(u => u.id === 99)); // [] (empty array, not undefined)The common mistake is treating find and filter as interchangeable when a value isn't found. Code written expecting filter's empty-array behavior will break if it's actually calling find, since undefined.someMethod() throws, while an empty array from filter fails silently instead.
Evaluates: whether the candidate can predict what each method returns on a no-match case specifically, since that's where confusing the two actually causes bugs, not in the happy path where both look similar.
4How do you chain array methods, and how do you reason about what each step produces?
const orders = [
{ id: 1, total: 250, status: "completed" },
{ id: 2, total: 80, status: "cancelled" },
{ id: 3, total: 400, status: "completed" },
{ id: 4, total: 150, status: "completed" }
];
const totalCompletedRevenue = orders
.filter(order => order.status === "completed")
.map(order => order.total)
.reduce((sum, total) => sum + total, 0);
console.log(totalCompletedRevenue); // 800Each step transforms the data into a new shape: filter narrows the array to completed orders, map extracts just the totals, reduce collapses those totals into a single number. The naive alternative uses one loop with all three concerns tangled together:
let total = 0;
for (const order of orders) {
if (order.status === "completed") {
total += order.total;
}
}Both are correct and, for a single pass like this, comparable in performance. The chained version is generally considered more readable because each step has one clear responsibility, though it's worth knowing that chaining several methods does mean iterating the array multiple times, once per method, which can matter for very large arrays.
Evaluates: whether the candidate can narrate the shape of the data after each step in the chain (an array of orders, then an array of numbers, then a single number), which is what separates someone who copies a chaining pattern from someone who actually understands it.
5What's the difference between some and every?
const nums = [2, 4, 6, 7];
console.log(nums.some(n => n % 2 !== 0)); // true (at least one odd number)
console.log(nums.every(n => n % 2 === 0)); // false (not all are even)Evaluates: knowing some returns true if any element passes the test, every returns true only if all elements do, and that both short-circuit as soon as the answer is determined, without checking every remaining element.
6How do you remove an item from an array without mutating the original?
const nums = [1, 2, 3, 4, 5];
const withoutThree = nums.filter(n => n !== 3);
console.log(withoutThree); // [1, 2, 3, 4, 5] minus the 3 -> [1, 2, 4, 5]
console.log(nums); // [1, 2, 3, 4, 5] -- unchangedEvaluates: reaching for filter (which returns a new array) instead of splice (which mutates in place), when the original array needs to stay untouched, a common requirement in frameworks like React where state shouldn't be mutated directly.
7What's the difference between splice and slice?
const arr = [1, 2, 3, 4, 5];
const sliced = arr.slice(1, 3);
console.log(sliced); // [2, 3]
console.log(arr); // [1, 2, 3, 4, 5] -- unchanged
const spliced = arr.splice(1, 2);
console.log(spliced); // [2, 3] -- the removed elements
console.log(arr); // [1, 4, 5] -- original array is mutatedEvaluates: knowing slice is non-mutating and returns a new array, while splice mutates the original and returns the removed elements. Confusing these two, given how similar their names are, is one of the most common small mistakes in real code.
8How do you calculate a sum and an average using reduce?
const scores = [80, 90, 70, 100];
const sum = scores.reduce((acc, n) => acc + n, 0);
const average = sum / scores.length;
console.log(sum); // 340
console.log(average); // 85Evaluates: the most standard reduce use case, included mainly as a baseline to make sure the candidate understands the accumulator pattern before being asked to apply it to something less obvious, like Q1's grouping example.
9How do array destructuring with defaults and skipped elements work?
const [first, , third = "default"] = [1, 2];
console.log(first); // 1
console.log(third); // default (index 2 doesn't exist, so the default applies)
const [a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(rest); // [3, 4, 5]Evaluates: knowing an empty slot (, ,) skips an element entirely, a default value only applies when the destructured position is undefined, and ...rest collects everything remaining into a new array.
10How do you check if two arrays are equal in content?
function arraysEqual(a, b) {
return a.length === b.length && a.every((val, i) => val === b[i]);
}
console.log(arraysEqual([1, 2, 3], [1, 2, 3])); // true
console.log(arraysEqual([1, 2, 3], [1, 2, 4])); // falseEvaluates: knowing arrays can't be compared with === (which checks reference identity, not content) and that a correct content comparison needs both a length check and an element-by-element comparison, commonly done with every.
How should you prepare for an array methods interview?
- Learn which methods mutate and which don't, as a fixed list.
sort,splice,push,pop,reversemutate.map,filter,slice,concatdon't. This single distinction prevents most of the bugs this guide covers. - Always supply a comparator to
sortfor numbers. It's a one-line fix, and forgetting it is one of the most common, and most avoidable, mistakes in this entire category. - Practise narrating chained methods. For any
filter().map().reduce()chain, be able to say out loud what shape the data is in after each step. That's the actual skill being tested, not the syntax.
Frequently asked questions
Who is this guide for, and what JavaScript experience does it assume? This guide assumes familiarity with basic array methods like map and forEach, covered in our anchor guide, and goes deeper into reduce, sorting, searching, and mutation behavior.
Why does sort() behave so differently with and without a comparator? Without one, sort() defaults to converting elements to strings and comparing them character by character, which works fine for words but breaks for numbers, since "10" sorts before "2" as strings.
Which array methods mutate the original array? The most commonly used mutating methods are push, pop, shift, unshift, splice, sort, and reverse. Everything else covered in this guide and the anchor guide, map, filter, slice, reduce, concat, returns a new array or value without touching the original.
Is chaining array methods slower than a single loop? For very large arrays, yes, slightly, since each method in the chain iterates separately. In practice this rarely matters at typical data sizes, and the readability benefit usually outweighs the small performance cost.
How is this different from the general JavaScript interview guide? The Top JavaScript Coding Interview Questions guide introduces map, flat, and Set-based deduplication alongside many other topics. This guide focuses specifically on array methods, especially reduce, sorting, and the mutation traps that come with them.
Related tutorials: Top JavaScript Coding Interview Questions · JavaScript Closures & Scope Interview Questions · JavaScript Async & Promises Interview Questions