Skip to main content
JavaScript arrays have a rich set of built-in methods. Interviews frequently test map, filter, reduce, and less common methods like flat, flatMap, and findIndex.

Transforming arrays

const nums = [1, 2, 3, 4, 5];

// map — transform each element, returns new array of same length
nums.map(n => n * 2);           // [2, 4, 6, 8, 10]

// filter — keep elements that pass the test, returns new array
nums.filter(n => n % 2 === 0);  // [2, 4]

// reduce — accumulate into a single value
nums.reduce((acc, n) => acc + n, 0); // 15

// reduceRight — same but right-to-left

Searching

const users = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" }
];

users.find(u => u.id === 2);       // { id: 2, name: "Bob" } or undefined
users.findIndex(u => u.id === 2);  // 1 or -1
users.some(u => u.name === "Bob"); // true — at least one matches
users.every(u => u.id > 0);       // true — all match
users.includes({ id: 1 });        // false — reference check

nums.indexOf(3);      // 2
nums.lastIndexOf(3);  // 2

Sorting & ordering

const arr = [3, 1, 4, 1, 5, 9];

// sort mutates the original array
arr.sort((a, b) => a - b);  // [1, 1, 3, 4, 5, 9] ascending
arr.sort((a, b) => b - a);  // [9, 5, 4, 3, 1, 1] descending

// String sort
["banana", "apple", "cherry"].sort((a, b) => a.localeCompare(b));
array.sort() without a comparator converts elements to strings and sorts lexicographically. [10, 9, 2].sort() gives [10, 2, 9]. Always provide a comparator for numbers.

Flattening

const nested = [1, [2, [3, [4]]]];

nested.flat();     // [1, 2, [3, [4]]]  — depth 1
nested.flat(2);    // [1, 2, 3, [4]]
nested.flat(Infinity); // [1, 2, 3, 4]

// flatMap — map then flatten one level
[[1, 2], [3]].flatMap(x => x); // [1, 2, 3]
[1, 2, 3].flatMap(n => [n, n * 2]); // [1, 2, 2, 4, 3, 6]

Mutating methods

These modify the original array — know when to avoid them:
arr.push(item);       // add to end, returns new length
arr.pop();            // remove from end, returns removed item
arr.unshift(item);    // add to start
arr.shift();          // remove from start
arr.splice(1, 2);     // remove 2 elements starting at index 1
arr.reverse();        // reverses in place

Non-mutating alternatives

// Instead of push
const newArr = [...arr, item];

// Instead of splice
const newArr = arr.filter((_, i) => i !== indexToRemove);

// Instead of reverse
const reversed = [...arr].reverse();

Common patterns

// Group by
const grouped = items.reduce((acc, item) => {
  const key = item.category;
  (acc[key] = acc[key] || []).push(item);
  return acc;
}, {});

// Unique values
const unique = [...new Set(arr)];

// Zip two arrays
const zip = (a, b) => a.map((val, i) => [val, b[i]]);

// Sum of object property
const total = items.reduce((sum, item) => sum + item.price, 0);

Common interview questions

Array.prototype.myMap = function(fn) {
  return this.reduce((acc, item, index) => {
    acc.push(fn(item, index, this));
    return acc;
  }, []);
};
Array.prototype.myFilter = function(fn) {
  return this.reduce((acc, item, index) => {
    if (fn(item, index, this)) acc.push(item);
    return acc;
  }, []);
};
  • forEach executes a callback for each element but always returns undefined. Use when you need side effects.
  • map executes a callback for each element and returns a new array with the results. Use when you need to transform data.
Never use map if you’re not using the returned array — use forEach instead.