reduce 接收一个回调函数和一个初始值,回调函数有四个参数:累计值、当前元素、当前索引、原数组。每一轮把返回值作为下一轮的累计值,遍历结束后返回最终结果。不传初始值时,第一轮会跳过第一个元素、直接拿它当累计值——数组为空且无初始值时会直接抛错。它等价于一个显式 for 循环不断改写同一个累积变量,但写法是声明式的、无副作用,链式调用时尤其清爽。
它是数组方法里表达力最强的一个:求和、求最大值、数组去重、按字段分组、把二维数组拍平,全都能一个 reduce 搞定。配合箭头函数写起来非常简洁,比如分组只需在累计对象上按 key 收集数组。可以说学会 reduce,就再也不需要在 for 循环里手动攒变量了。统计购物车总价、把接口返回的扁平列表按分类聚合成树形结构,都是它的典型舞台。
// 求和:初始值 0,逐项累加 const sum = [1, 2, 3, 4].reduce((acc, cur) => acc + cur, 0); console.log(sum); // 10 // 按字段分组:累计值是对象 const list = [ { name: '甲', dept: '前端' }, { name: '乙', dept: '后端' }, { name: '丙', dept: '前端' } ]; const grouped = list.reduce((acc, cur) => { (acc[cur.dept] = acc[cur.dept] || []).push(cur.name); return acc; }, {}); console.log(grouped); // { '前端': ['甲', '丙'], '后端': ['乙'] } // 数组去重:累计值是数组 const uniq = [1, 2, 2, 3, 3].reduce( (acc, cur) => (acc.includes(cur) ? acc : acc.concat(cur)), []); console.log(uniq); // [1, 2, 3]