You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义ES6 reduce函数模拟map功能的原理及疑问解答

自定义ES6 Reduce函数实现解析及问题解答

首先咱们先把这段代码清晰展示出来:

const reduce = (reducer, accumulator) => arr => { 
  const [first, ...rest] = arr 
  return arr.length ? reduce(reducer, reducer(accumulator, first))(rest) : accumulator 
} 
reduce((accum, current) => [...accum, current * 2], [])([1, 2, 3]);

代码工作原理拆解

这个reduce是个柯里化函数(也就是分多次接收参数的函数),整体执行流程可以拆成两步:

  1. 第一次调用:传入reducer(定义元素处理逻辑的函数)和accumulator(初始累积值),返回一个专门等待接收目标数组的新函数。
  2. 调用返回的新函数并传入要处理的数组后,内部会做这些操作:
    • 用解构赋值把数组拆成第一个元素first和剩余元素组成的rest数组。
    • 判断数组长度:如果数组不为空,就递归调用reduce——此时把更新后的累积值(调用reducer用当前累积值和first计算得到)传入,同时把rest作为下一次要处理的数组;如果数组为空,就返回最终的累积值。

拿示例中的调用来说:

  • 初始调用reduce((accum, current) => [...accum, current * 2], [])得到一个等待数组的函数,随后传入[1,2,3]。
  • 第一次处理:first=1,rest=[2,3],调用reducer([],1)得到[2],接着递归调用reduce(...)处理[2,3]。
  • 第二次处理:first=2,rest=[3],调用reducer([2],2)得到[2,4],递归处理[3]。
  • 第三次处理:first=3,rest=[],调用reducer([2,4],3)得到[2,4,6],递归处理空数组。
  • 空数组触发返回逻辑,最终结果就是[2,4,6]。

问题1:为何在reducer函数中...accum作为数组展开的第一个参数而非最后一个?该示例中...accum的具体含义是什么?

...accum的具体含义

...是ES6的扩展运算符,在这里...accum的作用是把accum数组里的所有元素逐个“拆解”出来,放到新数组的对应位置。比如accum是[2],...accum就相当于把2单独提取出来,直接作为新数组的一部分。

为什么放在第一个参数

这么做是为了保证处理后数组的顺序和原数组完全一致:

  • 如果把...accum放在前面:每次处理新元素时,先把之前累积的所有元素放到新数组里,再追加当前元素的处理结果(current*2),最终结果的顺序和原数组一一对应——原数组是[1,2,3],结果就是[2,4,6]。
  • 如果把...accum放在后面:新数组会先放当前元素的处理结果,再把之前的累积元素追加到后面,结果就会变成[6,4,2],完全倒序,这显然不符合我们模拟map函数的预期。

问题2:为何初始调用reduce时,第一个reducer并未传入任何参数?

其实你是混淆了柯里化函数的调用层级——初始调用reduce时是传入了reducer参数的!
看示例里的调用:reduce((accum, current) => [...accum, current * 2], [])([1, 2, 3]),这里第一个参数(accum, current) => [...accum, current * 2]就是我们要传入的reducer函数,第二个参数[]是初始累积值。

这个reduce函数采用了柯里化设计,分两次完成调用:

  1. 第一次调用reduce(reducer函数, 初始累积值):完成前两个参数的传递,返回一个等待接收目标数组的函数。
  2. 第二次调用(目标数组):才真正启动数组的遍历处理逻辑。

所以并不是没传reducer,只是它的调用形式是分两步的柯里化写法而已。


内容的提问来源于stack exchange,提问作者Mat.Now

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:06:18