JavaScript array methods interview questions, with answers
Array questions in JavaScript interviews are rarely about loops. They are about the built-in methods — what each one returns, which ones change the array they are called on, and what they pass to your callback. A wrong assumption about any of those gives code that runs without an error and produces the wrong answer, which is exactly what interviewers like to ask about. Every output shown was produced by running the code in Node.js.
The questions start with the three methods every answer uses, then sorting and mutation, then searching, deduplicating and building arrays. Then take the free JavaScript diagnostic — ten questions across every JavaScript topic in the bank — to see which of these you can explain but not yet predict.
The questions, with answers
1.What is the difference between map, filter and reduce in JavaScript?
In short: map returns a new array of the same length with each element transformed, filter returns the elements that pass a test, and reduce folds the whole array into one value of any type.
All three leave the original array alone and call your callback with the element, its index and the array. map is for transforming, filter for selecting and reduce for accumulating: a sum, a count per key, a lookup object built from a list. reduce takes a callback of the accumulator and the element and, ideally, an initial value as its second argument, as below; supplying one makes the result's type obvious and makes the call safe on an empty array, which would otherwise throw. Chaining reads naturally, filter then map then reduce, at the cost of one pass and one intermediate array per step, which matters only for very large arrays. forEach, by contrast, returns undefined and exists for side effects.
const marks = [45, 82, 67, 91]; const passed = marks .filter((m) => m >= 50) .map((m) => m + 5); console.log(passed.join(",")); // 87,72,96 const sum = marks.reduce( (acc, m) => acc + m, 0); console.log(sum); // 285
2.How does sort() compare elements, and how do you sort numbers in JavaScript?
In short: Without a comparator, sort converts elements to strings and orders them by UTF-16 code units, so numbers sort as text; pass (a, b) => a - b for ascending numeric order.
The default comparison is by string, which is why this page's sample puts 100 before 9. A comparator returns a negative number to put a first, a positive one to put b first, and zero to keep their order, so a - b sorts ascending and b - a descending. Returning a boolean, as in (a, b) => a > b, is a common bug: true and false convert to 1 and 0, never a negative number, and the result depends on the engine's algorithm. sort works in place and returns the same array; toSorted, from ES2023, returns a sorted copy, as below. Since ES2019 sort is stable, so equal elements keep their previous order. For words, compare with localeCompare, which orders letters alphabetically regardless of case.
const n = [25, 100, 3]; const asc = n.toSorted( (a, b) => a - b); console.log(asc.join()); // 3,25,100 console.log(n.join()); // 25,100,3 const w = ["b", "a", "C"]; w.sort((x, y) => x.localeCompare(y)); console.log(w.join()); // a,b,C
3.Which array methods mutate the array in JavaScript, and which return a new one?
In short: push, pop, shift, unshift, splice, sort, reverse and fill change the array in place; map, filter, slice, concat, flat and the ES2023 toSorted, toReversed, toSpliced and with return new arrays.
The distinction matters most where data is shared: sorting an array held in React state in place changes data other code holds and can skip a re-render, because the reference has not changed. slice(start, end) copies part of an array and never modifies it; splice(start, deleteCount, ...items) removes and inserts in place and returns the removed items, as below — the names differ by one letter and interviewers love the pair. sort and reverse return the same array they changed, which hides the mutation in chained code. When unsure, copy first, with [...arr] or arr.slice(), or use the non-mutating ES2023 versions.
const a = [1, 2, 3, 4]; const s = a.slice(1, 3); const r = a.splice(1, 2); console.log(s.join()); // 2,3 console.log(r.join()); // 2,3 console.log(a.join()); // 1,4
4.What is the difference between find, filter, some and every in JavaScript?
In short: filter returns every matching element in a new array, find returns the first match or undefined, some reports whether any element matches, and every whether all of them do.
Choosing the right one says what you mean and saves work: find, some and every stop at the first element that settles the answer, while filter always scans the whole array. findIndex returns the position instead of the element, or -1 when nothing matches, and findLast and findLastIndex search from the end. Two edge cases come up: every returns true for an empty array and some returns false, because there is no counterexample and no example, as the last line below shows. To test whether a value is present, includes is simpler than some, and indexOf is the older way to find its position.
const u = [ { id: 1, ok: false }, { id: 2, ok: true }, ]; const h = u.find((x) => x.ok); console.log(h.id); // 2 const y = u.some((x) => x.ok); console.log(y); // true console.log([].every(Boolean)); // true
5.How do you remove duplicates from an array in JavaScript?
In short: For primitives, [...new Set(arr)] keeps the first occurrence of each value, in order; for objects, deduplicate by a key with a Map or with filter and findIndex.
A Set holds each value once, and spreading it back into an array keeps first-seen order, so the one-liner below is both short and O(n). A Set compares primitives by value but objects by reference, so two objects with the same contents are both kept. For an array of objects, pick the property that defines a duplicate and keep one element per key: new Map(arr.map(o => [o.id, o])).values() is concise, though it keeps the last element for each key, so check has() before setting when the first must win. The filter-and-indexOf version is O(n²), fine only for short arrays, and interviewers often ask for its complexity as the follow-up.
const ids = [3, 1, 3, 2, 1]; const uniq = [...new Set(ids)]; console.log(uniq.join()); // 3,1,2
6.What do flat and flatMap do in JavaScript?
In short: flat(depth) returns a new array with nested arrays spliced in up to the given depth, one by default; flatMap maps each element and then flattens the results by one level.
flat() handles the common case of one level of nesting, as the first result below shows, and flat(Infinity) flattens any depth. Empty slots in sparse arrays are removed along the way. flatMap(fn) is map(fn).flat() in a single pass, and it doubles as a way to filter and map at once: return [] to drop an element, [x] to keep one, or several values to expand it, as the split below does. Before ES2019 the usual interview answer for flattening was recursion with reduce and concat, and it is still worth being able to write, because the follow-up is often to implement flat yourself for an arbitrary depth.
const n = [1, [2, [3, [4]]]]; console.log(n.flat().length); // 3 const all = n.flat(Infinity); console.log(all.join()); // 1,2,3,4 const w = ["hi there", "ok"] .flatMap((s) => s.split(" ")); console.log(w.length); // 3
7.How do Array.from and the spread operator create arrays?
In short: Both turn iterables such as strings, Sets and Maps into arrays; Array.from also accepts array-like objects with a length and takes a mapping function, which makes it the tool for building ranges.
[...iterable] works on anything with a Symbol.iterator method: strings, Sets, Maps, NodeLists and generator results. Array.from covers the same ground plus array-like objects, such as { length: 4 } or a function's arguments, and its second argument maps each element as it is created, which makes it the idiomatic way to build a range or a table of values, as below. new Array(3) creates a sparse array of three empty slots that map skips, a frequent surprise shown by the counter below, while Array.from({ length: 3 }) creates three real undefined values. Array.of(3) creates [3], avoiding the Array constructor's single-number ambiguity.
const r = Array.from( { length: 4 }, (_, i) => i * i ); console.log(r.join()); // 0,1,4,9 let called = 0; Array(3).map(() => called++); console.log(called); // 0
How the diagnostic asks it
One question from the JavaScript bank, exactly as a sitting would show it. The bank has 4 on arrays and 30 across JavaScript.
What does this code print?
console.log([10, 9, 1, 100].sort().join(","));- 11,9,10,100
- 21,10,100,9correct
- 3100,10,9,1
- 49,10,100,1
With no compare function, sort() converts elements to strings and compares them character by character, so "10" and "100" sort before "9", giving 1,10,100,9. 1,9,10,100 is numeric order, which needs sort((a, b) => a - b). 100,10,9,1 is descending order. 9,10,100,1 is no ordering sort() produces. sort() also sorts the array in place and returns it.
Measure it
Reading answers tells you what’s true. A diagnostic tells you what you get wrong.
10 JavaScript questions across its topics, easy to hard, about fifteen minutes. You get a readiness figure with the arithmetic shown, the topics you missed named, and a practice set sized for today. Free: 1 diagnostic a month and 15 problems a day. No card.