JavaScript reduce方法中累加器未显式赋值却自动更新的原理是什么?
累加器更新的核心原理:不存在"自动感知"的魔法
你观察到的累加器自动变化,完全是Array.prototype.reduce内置的固定运行规则,全程没有隐藏的自动修改逻辑。
reduce 的标准执行流程
当你调用arr.reduce(callback)且没有传入第二个参数作为初始累加值时,reduce会严格按照以下规则跑完全程:
- 第一步:把原数组的第0位元素,作为第一次执行回调时的
acc入参,把原数组的第1位元素作为第一次执行回调时的curr入参。 - 每一轮回调执行结束后,reduce会把回调函数内部
return的返回值,直接存储为下一轮回调要使用的新acc值。这个步骤是reduce的内置行为,不需要你手动在代码里写类似acc = 新值的语句——你只要通过return把要传给下一轮的值交出来就行。 - 重复以上步骤直到遍历完数组所有元素,最后一轮回调的返回值就是reduce方法的最终返回结果。
对应到你代码的逐轮执行细节
你觉得累加器“自己变了”,本质是你把注意力全放在局部变量results的构造过程上,忽略了回调里return results这个动作本身,就是触发累加器更新的指令:
- 第一轮回调(处理arr2时)
- 入参:
acc是arr1([5,10,15,20,7,3]),curr是arr2([15,88,1,5,7,21]) - 循环筛选得到
results = [15,5,7] - 执行
return results——reduce引擎立刻把这个数组存起来,作为下一轮的累加器值。
- 入参:
- 第二轮回调(处理arr3时)
- 入参:
acc是上一轮回调return的[15,5,7],curr是arr3([1,10,15,5,20,21]) - 循环筛选得到
results = [15,5] - 执行
return results——这是最后一轮遍历,这个值就是reduce的最终返回结果。
- 入参:
常见认知误区
很多人对reduce的误解,都来自于觉得“累加器必须要在回调里被手动修改才会更新”——比如必须给acc数组push元素、改acc的对象属性,才算生效。但实际上这个理解从根上就错了:
你根本不需要碰入参传进来的
acc值,只要回调最后有明确的return,reduce就会把你return的内容原样作为下一轮的累加器。不管你return的是修改过的原acc、临时新造的数组、数字、字符串还是其他任意类型的值,这个规则都不会变。
举个极简的例子就能直观看懂这个逻辑:
[1, 2, 3].reduce((acc, curr) => { console.log(`当前acc值: ${acc}, 当前遍历项: ${curr}`); return acc + 10; // 没有修改入参acc,只是返回了一个新值 }); // 执行日志: // 当前acc值: 1, 当前遍历项: 2 // 当前acc值: 11, 当前遍历项: 3 // 最终返回值: 21
这里全程没有给入参的acc做任何赋值或修改,只是靠return语句传递新值,累加器就完成了更新。
内容的提问来源于stack exchange,提问作者Van Nguyen
相关产品推荐
相关产品推荐

