JavaScript Array Methods
Key Learning Objectives
Master core array iteration methods: map, filter, reduce, find, some, and every.
Understand why forEach returns undefined and mutates state via side effects while map returns a new array.
Recognize the arrow function block body return trap in filter and map callbacks.
Grasp reduce accumulator initialization and behavior on empty arrays.
The Interview Problem
What is logged to the console when the following JavaScript code executes, and how do missing return statements and method return values affect the outcome?
1const nums = [1, 2, 3, 4];23const mapped = nums.map((n) => {4 if (n % 2 === 0) return n * 2;5});67const filtered = nums.filter((n) => {8 n > 1;9});1011const reduced = [1, 2, 3].reduce((acc, curr) => acc + curr, 10);1213const list = [1, 2];14const forEachRet = list.forEach((n, i, arr) => {15 arr[i] = n * 10;16});1718console.log(19 mapped.join(','),20 filtered.length,21 reduced,22 String(forEachRet),23 list.join(',')24);
Predict Console Output
Select the option that matches what standard ECMAScript prints to the console:
undefined,4,undefined,8 0 16 undefined 10,20
4,8 3 16 [10,20] 10,20
undefined,4,undefined,8 3 6 undefined 1,2
4,8 0 16 undefined 1,2
V8 Engine Execution Trace
Step 1 of 8 (Line 1)nums array is initialized in heap memory with length 4.
Deep Technical Breakdown
Core Mental Models for JavaScript Array Methods
- map vs forEach:
Array.prototype.map(): A pure projection function. Transforms every element into a new element in a brand new array of identical length. If a branch omitsreturn, that slot becomesundefined.Array.prototype.forEach(): Designed solely for side effects (e.g. logging, API calls, mutating external data). It unconditionally returnsundefinedaccording to the ECMAScript specification.
- The Arrow Function Block Return Pitfall in filter:
- Concise body:
nums.filter(n => n > 1)has an implicit return. - Block body:
nums.filter(n => { n > 1; })contains an expression statement without thereturnkeyword. It returnsundefined, which coerces tofalse, discarding every element.
- Concise body:
- reduce Accumulator Initialization Rules:
arr.reduce(callback, initialValue): IfinitialValueis provided,accstarts atinitialValueand the callback runsarr.lengthtimes.- If
initialValueis omitted,accstarts asarr[0], the first iteration starts at index 1, and the callback runsarr.length - 1times. - Fatal Edge Case: Calling
reduce()without an initial value on an empty array ([].reduce(...)) throwsTypeError: Reduce of empty array with no initial value.
Common Traps & Mistakes
Calling `[].reduce((acc, curr) => acc + curr)` without an initial value, resulting in an unhandled TypeError crash in production.
Confusing mutating methods (`push`, `pop`, `shift`, `unshift`, `splice`, `sort`, `reverse`) with non-mutating methods (`map`, `filter`, `slice`, `concat`, `toSorted`, `toReversed`).
Expecting `forEach` to break early using `return` or `break`. `return` only exits the current callback iteration, and `break` is a syntax error inside a function callback. Use `for...of`, `some()`, or `find()` instead.
FAANG Follow-Up Probes
Probe #1
How would you implement a polyfill for Array.prototype.reduce that correctly handles sparse arrays and missing initialValue?
Probe #2
Why can you not stop or break out of an Array.prototype.forEach loop, and how do you achieve short-circuiting with some() or every()?
Probe #3
What are the newly standardized ECMAScript immutable array methods (toSorted, toReversed, toSpliced, with), and how do they benefit React state updates?
