Advanced Usage of JavaScript Array.reduce: Techniques, Examples, and Performance
This article provides a comprehensive guide to JavaScript's ES5 array.reduce method, covering its definition, syntax, simple and advanced use cases, performance comparison with other iteration methods, compatibility notes, and practical code examples for developers seeking deeper mastery.
Background
The reduce method, introduced in ES5, is a powerful array iterator that many developers overlook in favor of forEach , filter , and map . This article revives reduce by explaining its syntax, parameters, and execution flow.
Definition and Syntax
Definition: Executes a custom accumulator on each array element and returns a single aggregated value.
Signature: array.reduce((t, v, i, a) => {}, initValue)
Parameters callback (required): The accumulator function. initValue (optional): Initial accumulator value.
Accumulator Parameters
t (total): Accumulated result.
v (value): Current element.
i (index, optional): Current index.
a (array, optional): Original array.
Process
Initialize t with initValue or the first array element.
Iterate over the array, applying the callback to update t .
After the last element, return the final t .
Simple Example
const arr = [3, 5, 1, 4, 2];
const sum = arr.reduce((t, v) => t + v);
// equivalent to
const sumWithInit = arr.reduce((t, v) => t + v, 0);Advanced Use Cases (20 scenarios)
Below are representative examples that demonstrate how reduce can replace other methods or solve complex problems.
Replace map : const doubled = arr.reduce((t, v) => [...t, v * 2], []);
Replace filter : const filtered = arr.reduce((t, v) => v > 1 ? [...t, v] : t, []);
Combine map and filter : const result = arr.reduce((t, v) => v * 2 > 2 ? [...t, v * 2] : t, []);
Chunk array : function Chunk(arr = [], size = 1) { return arr.length ? arr.reduce((t, v) => (t[t.length-1].length===size ? t.push([v]) : t[t.length-1].push(v), [[]]) : []; }
Array difference : function Difference(arr = [], oarr = []) { return arr.reduce((t, v) => (!oarr.includes(v) && t.push(v), t), []); }
Fill range : function Fill(arr = [], val = "", start = 0, end = arr.length) { if (start < 0 || start >= end || end > arr.length) return arr; return [...arr.slice(0,start), ...arr.slice(start,end).reduce((t,v)=>{t.push(val||v);return t;}, []), ...arr.slice(end)]; }
Flatten nested arrays : function Flat(arr = []) { return arr.reduce((t,v) => t.concat(Array.isArray(v) ? Flat(v) : v), []); }
Remove duplicates : function Uniq(arr = []) { return arr.reduce((t,v) => t.includes(v) ? t : [...t, v], []); }
Find max/min : function Max(arr = []) { return arr.reduce((t,v) => t > v ? t : v); } function Min(arr = []) { return arr.reduce((t,v) => t < v ? t : v); }
Unzip matrix : function Unzip(arr = []) { return arr.reduce((t,v) => (v.forEach((w,i)=>t[i].push(w)), t), Array.from({length: Math.max(...arr.map(v=>v.length))}).map(()=>[])); }
Count occurrences : function Count(arr = []) { return arr.reduce((t,v) => (t[v] = (t[v]||0)+1, t), {}); }
Record positions : function Position(arr = [], val) { return arr.reduce((t,v,i) => (v===val && t.push(i), t), []); }
Group by key : function Group(arr = [], key) { return key ? arr.reduce((t,v) => (t[v[key]] = t[v[key]] || [], t[v[key]].push(v), t), {}) : {}; }
Keyword statistics : function Keyword(arr = [], keys = []) { return keys.reduce((t,k) => (arr.some(w => w.includes(k)) && t.push(k), t), []); }
String reverse : function ReverseStr(str = "") { return str.split("").reduceRight((t,v) => t+v, ""); }
Sum and product : function Accumulation(...vals) { return vals.reduce((t,v) => t+v, 0); } function Multiplication(...vals) { return vals.reduce((t,v) => t*v, 1); }
Asynchronous accumulation : async function AsyncTotal(arr = []) { return arr.reduce(async (t,v) => { const at = await t; const todo = await Todo(v); at[v] = todo; return at; }, Promise.resolve({})); }
Fibonacci sequence : function Fibonacci(len = 2) { const arr = [...new Array(len).keys()]; return arr.reduce((t,v,i) => (i>1 && t.push(t[i-1]+t[i-2]), t), [0,1]); }
Extract specific keys from object : function GetKeys(obj = {}, keys = []) { return Object.keys(obj).reduce((t,k) => (keys.includes(k) && (t[k] = obj[k]), t), {}); }
Compatibility and Performance
According to caniuse.com , reduce enjoys full support across modern browsers, making it safe for production use.
Performance tests comparing for-in , forEach , map , and reduce on a 100,000‑element array show that reduce consistently has the lowest execution time (≈2.8 ms) versus forEach (≈3.7 ms) and map (≈3.6 ms), confirming its efficiency for cumulative operations.
// Create an array of length 100000
const list = [...new Array(100000).keys()];
// for-in
console.time("for-in");
let r1 = 0;
for (let i = 0; i < list.length; i++) { r1 += i + 1; }
console.timeEnd("for-in");
// forEach
console.time("forEach");
let r2 = 0;
list.forEach(v => r2 += v + 1);
console.timeEnd("forEach");
// map
console.time("map");
let r3 = 0;
list.map(v => { r3 += v + 1; return v; });
console.timeEnd("map");
// reduce
console.time("reduce");
const r4 = list.reduce((t,v) => t + v + 1, 0);
console.timeEnd("reduce");Conclusion
The article demonstrates that reduce is not only versatile for a wide range of data‑processing tasks but also performant and fully compatible. Readers are encouraged to experiment with the presented patterns, share their own use cases, and apply reduce confidently in future projects.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.