JavaScript Coding Interview: Array Method Pitfalls to Avoid

JavaScript Coding Interview: Array Method Pitfalls to Avoid

JavaScript's array methods make interview code short and readable. They also hide some of the most common bugs in live rounds. Numbers sort as strings, map(parseInt) returns NaN, a 2D grid turns out to be one shared row, and a return inside forEach does nothing you expected.

This guide covers the JavaScript coding interview array method pitfalls that come up most, why each one happens, and the fix you can type without thinking. All examples run in a modern Node.js or browser console.

Pitfall 1: sort() compares strings by default

[10, 9, 1, 100].sort();          // [1, 10, 100, 9]
[10, 9, 1, 100].sort((a, b) => a - b);  // [1, 9, 10, 100]

Without a comparator, sort converts elements to strings and compares them by UTF-16 code units. For numbers, always pass (a, b) => a - b (ascending) or (a, b) => b - a (descending).

For sorting pairs or intervals:

intervals.sort((a, b) => a[0] - b[0] || a[1] - b[1]);

The || breaks ties on the second element, because 0 is falsy.

Pitfall 2: sort() and reverse() mutate in place

const words = ['b', 'a', 'c'];
const sorted = words.sort();
sorted === words;   // true: the original array changed

If the caller's array shouldn't change, copy it first, [...arr].sort(...), or use toSorted / toReversed where your runtime supports them (ES2023). Say it out loud: "I'll copy so I don't mutate the input."

Pitfall 3: map(parseInt)

['1', '2', '3'].map(parseInt);   // [1, NaN, NaN]

map passes (value, index, array), and parseInt takes (string, radix). Index 1 becomes radix 1, which is invalid, and '3' in radix 2 is NaN. Fix:

['1', '2', '3'].map(Number);           // [1, 2, 3]
['1', '2', '3'].map(s => parseInt(s, 10));

Pitfall 4: Array(n).fill([]) shares one array

const grid = Array(3).fill([]);
grid[0].push(1);
// grid is [[1], [1], [1]]: every row is the same object

fill puts the same reference in every slot. Build rows independently:

const grid = Array.from({ length: m }, () => Array(n).fill(0));
const buckets = Array.from({ length: k }, () => []);

fill(0) is safe because numbers are primitives. The problem only comes up with objects and arrays.

Pitfall 5: return inside forEach doesn't return

function hasTwo(arr) {
  arr.forEach(x => {
    if (x === 2) return true;   // returns from the callback only
  });
  return false;
}
hasTwo([1, 2, 3]);   // false

forEach can't be stopped early, except by throwing. Use the method that matches what you mean:

You wantUse
Does any element match?some
Do all elements match?every
First matching elementfind (returns undefined if none)
Index of first matchfindIndex (returns -1 if none)
Early exit with complex logica plain for...of loop with break / return

In interviews, a plain for loop is often the clearest choice anyway.

Pitfall 6: reduce on an empty array

[].reduce((a, b) => a + b);      // TypeError: Reduce of empty array with no initial value
[].reduce((a, b) => a + b, 0);   // 0

Always pass an initial value. It also makes the accumulator's type obvious: 0 for sums, {} or new Map() for counts, [] for building lists.

Pitfall 7: shift() in a BFS queue

while (queue.length) {
  const node = queue.shift();   // O(n) per call in typical engines
  // ...
}

shift re-indexes the array, so a large BFS can become quadratic. For interview-sized inputs it's usually fine, but it's worth knowing the alternative:

const queue = [start];
let head = 0;
while (head < queue.length) {
  const node = queue[head++];
  for (const next of neighbors(node)) {
    if (!seen.has(next)) {
      seen.add(next);
      queue.push(next);
    }
  }
}

Say it: "I'm using a head pointer instead of shift so dequeue stays O(1)."

Pitfall 8: indexOf vs includes with NaN, and strict equality

[NaN].indexOf(NaN);    // -1
[NaN].includes(NaN);   // true
[1, 2, 3].includes('2');   // false (strict comparison, no coercion)

Inputs parsed from strings can surprise you here. Normalize types before you search.

Pitfall 9: slice vs splice

const a = [1, 2, 3, 4, 5];
a.slice(1, 3);    // [2, 3]; a unchanged (end index exclusive)
a.splice(1, 2);   // [2, 3]; a is now [1, 4, 5] (start, deleteCount)

slice(start, end) copies. splice(start, count, ...items) mutates. Mixing them up is a classic off-by-something bug.

Pitfall 10: shallow copies of 2D arrays

const copy = [...grid];
copy[0][0] = 9;   // also changes grid[0][0]

Spread copies the outer array only. For a grid of primitives:

const copy = grid.map(row => [...row]);

structuredClone(grid) works too in modern runtimes, but the map version is clear enough and easy to explain.

Pitfall 11: Math.max on empty or huge arrays

Math.max();             // -Infinity
Math.max(...[]);        // -Infinity

Check for empty input explicitly. Spreading a very large array into Math.max can also exceed the engine's argument limit and throw a RangeError. A loop or reduce with an initial value avoids that.

A few safe idioms

const last = arr.at(-1);                       // last element
const counts = new Map();
for (const x of arr) counts.set(x, (counts.get(x) ?? 0) + 1);
const unique = [...new Set(arr)];
const flat = nested.flat();                    // one level
const pairs = Object.entries(obj);             // [key, value][]

Prefer Map and Set over plain objects for counting and membership. Keys keep their type (the number 1 stays a number), and there's no prototype to worry about.

Talk track while coding

"I'm passing a numeric comparator because the default sort is lexicographic."

"I'll build the grid with Array.from so each row is its own array."

"I'm using some instead of forEach because I want to stop at the first match."

These short sentences show the interviewer you know the language, and they keep you from going quiet.

Soft practice note

These pitfalls rarely show up when you're relaxed. They show up when the clock is running and someone is watching. If you want timed, out-loud practice to make the safe idioms automatic, Luna Interview is built for calm, structured interview rehearsal and prep before the real round.

Pre-interview checklist

Learn the handful of traps once, and JavaScript's array methods go back to saving you time.