Functional Array Methods (JS)
debt(d3/e1/b3/t5)
Closest to 'default linter catches the common case' (d3). The detection_hints list ESLint as the tool with automated: yes, and the code_pattern describes for-loops building result arrays and forEach-with-side-effects — both patterns ESLint rules (e.g. prefer-array-methods or no-array-for-each) can flag out of the box or with common plugins.
Closest to 'one-line patch or single-call swap' (e1). The quick_fix is literally a direct substitution — replace forEach with map, filter()[0] with find(), map+flat with flatMap. Each fix is a single call replacement at the usage site.
Closest to 'localised tax' (b3). The misuse (e.g. forEach instead of map) is scoped to individual call sites. It doesn't propagate architecture-wide — each instance is independently fixable and doesn't shape the broader codebase. The applies_to covers web and cli broadly, but the impact of each mistake is local.
Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The misconception field explicitly states that forEach and map appear interchangeable since both iterate, but forEach returns undefined and discards return values while map collects them. This is a well-known documented gotcha that many developers encounter and learn, but it's not catastrophic or system-wide — scoring t5 exactly.
Also Known As
TL;DR
Explanation
JavaScript arrays have rich functional methods. map(fn) transforms every element, returning a new array. filter(fn) keeps elements where fn returns truthy. reduce(fn, init) folds to a single value — the most powerful but most misused. find(fn) returns the first matching element or undefined. findIndex(fn) returns its index or -1. some(fn) returns true if any element matches; every(fn) if all match. flat(depth) flattens nested arrays; flatMap(fn) maps then flattens one level (more efficient than map().flat()). Array.from(iterable, mapFn) converts iterables to arrays with optional mapping. sort() mutates the original — use [...arr].sort() to sort a copy. All these methods compose cleanly: users.filter(u => u.active).map(u => u.email).join(', ').
Diagram
flowchart LR
ARR[array] -->|map| TRANSFORM[new array<br/>same length<br/>values transformed]
ARR -->|filter| SUBSET[new array<br/>shorter<br/>matching items only]
ARR -->|reduce| ACCUM[single value<br/>sum object string etc]
ARR -->|find| FIRST[first matching item<br/>or undefined]
ARR -->|some| BOOL1[true if any match]
ARR -->|every| BOOL2[true if all match]
ARR -->|flatMap| FLAT[map then flatten<br/>one level]
INFO[All non-mutating<br/>original array unchanged]
style ARR fill:#6e40c9,color:#fff
style TRANSFORM fill:#238636,color:#fff
style SUBSET fill:#1f6feb,color:#fff
style ACCUM fill:#d29922,color:#fff
style INFO fill:#238636,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Using forEach when map is needed — forEach discards return values; map collects them.
- Using filter().map() when flatMap() would be cleaner for mapping and flattening.
- Not using find() when you want the first matching element — filter()[0] returns undefined awkwardly.
- Mutating the original array in map() callbacks — map should return a new transformed value.
Code Examples
// Manual loop instead of array method:
const names = [];
for (let i = 0; i < users.length; i++) {
names.push(users[i].name); // Use: users.map(u => u.name)
}
// forEach misused for transformation:
const doubled = [];
numbers.forEach(n => doubled.push(n * 2)); // Use: numbers.map(n => n * 2)
const totals = orders
.filter(o => o.status === 'paid')
.map(o => o.amount)
.reduce((sum, amt) => sum + amt, 0);