arr.reduce方法返回值疑问:为何代码返回数组最后一项而非累加器(数组转键值对象实现场景)
Great question—let’s break down exactly what’s happening here, step by step.
First, a quick recap of how Array.reduce works: it loops through each element in your array, passing two core values to your callback function: the accumulator (the object/value you’re building up over iterations) and the current element. Whatever your callback returns becomes the accumulator for the next iteration, and the final accumulator is what reduce spits out as its result.
The Root of Your Bug
Your incorrect implementation uses an arrow function with an implicit return:
function groupByid(arr){ return arr.reduce( (obj, value) => obj[value.id] = value, {} ); }
The critical detail here is that assignment expressions return the value being assigned, not the object you’re assigning to. So when you write obj[value.id] = value, this line evaluates to value itself—not the obj accumulator you’re trying to build.
Let’s walk through each iteration to see the domino effect:
- First iteration:
objstarts as the empty{}. You assignobj['john'] = {id: 'john', ...}, and the callback returns this John user object (not theobjcontainer). - Second iteration: Now the accumulator is no longer the empty object—it’s the John user object. You try to assign
obj['ann'] = {id: 'ann', ...}(butobjis now a user object, not a container!), and the callback returns the Ann user object. - Third iteration: The accumulator is the Ann user object. Assign
obj['pete'] = {id: 'pete', ...}, return the Pete user object. - Final result:
reducereturns the last value the callback returned—the Pete user object.
Why the Correct Code Works
Your working implementation uses curly braces around the callback logic, which forces you to explicitly return the accumulator:
function groupByid(arr){ return arr.reduce( (obj, value) => { obj[value.id] = value; return obj; // This line makes all the difference! }, {} ); }
By returning obj after each assignment, you ensure the accumulator stays the container object through every iteration. Each loop modifies the same object and passes it along, resulting in the full key-value map you expect.
A Simplified Demo to Drive It Home
Here’s a tiny example that shows the difference clearly:
// Wrong: returns 3, not the built object console.log([1,2,3].reduce((acc, val) => acc[val] = val, {})); // Right: returns {1:1, 2:2, 3:3} console.log([1,2,3].reduce((acc, val) => { acc[val] = val; return acc; }, {}));
Key Takeaway
Arrow functions with a single expression implicitly return that expression’s result. When that expression is an assignment, you get the assigned value back—not the object you modified. Always explicitly return the accumulator in your reduce callback when building up an object or array, unless you intentionally want to pass a different value to the next iteration.
内容的提问来源于stack exchange,提问作者Malik Yasa

