关于Array.reduce()返回拼接结果而非总和及语法差异的技术咨询
我来帮你逐个拆解这三个关于reduce的问题,都是新手使用reduce时很容易踩的坑:
1. [object Object]是什么?为什么结果是字符串拼接而非正确总和?
先看你示例1的代码:
const items = [ { name: "Bike", price: 100 }, { name: "TV", price: 200 }, { name: "Album", price: 10 }, { name: "Book", price: 5 }, { name: "Phone", price: 500 }, { name: "Computer", price: 1000 }, { name: "Keyboard", price: 25 }, ]; const total = items.reduce((total, amount) => { return total + amount.price; }); console.log("total", total);
这里的核心问题是reduce没有初始值时的默认行为:当你不给reduce传第二个参数(初始值),它会把数组的第一个元素作为初始的total值——也就是这里的{ name: "Bike", price: 100 }这个对象。
第一次迭代时,执行total + amount.price,也就是一个对象加上数字200。JavaScript遇到不同类型的值相加时,会自动做类型转换:对象会被转换成字符串,而对象默认的toString()方法返回的就是[object Object]。所以第一次运算后得到的是"[object Object]" + 200 = "[object Object]200",这是一个字符串。
之后每一次迭代,都是把这个字符串和下一个amount.price(数字)拼接,数字会被转换成字符串,最终就得到了[object Object]200105500100025这个结果,而不是你期望的数字相加总和。
2. 为什么添加, 0会得到正确总和?是转换price为数字吗?
看示例2的代码:
const total = items.reduce((total, amount) => { return total + amount.price; }, 0);
当你给reduce传入第二个参数0时,这个值就成了total的初始值——是一个数字类型。
第一次迭代时,total是0,加上amount.price(100,本身就是数字),结果是100(数字相加)。之后每一次迭代,都是数字和数字相加,所以最终能得到正确的总和1840。
这里并不是把price转换成数字,因为你的price本身就是数字类型。关键是初始值的类型决定了运算的类型:初始值是数字,所以所有后续的+都是数字加法,而不是字符串拼接。
3. 箭头函数里写不写return有什么差异?为什么示例3返回undefined?
看示例3的代码:
const total = items.reduce((total, amount) => {total + amount.price}, 0);
箭头函数有两种写法,差异就在这里:
- 简洁体(无大括号):如果箭头函数直接写表达式(没有
{}包裹),会自动返回这个表达式的结果,比如(a,b) => a + b,相当于(a,b) => { return a + b; }。 - 块体(有大括号):如果用
{}包裹函数体,就必须显式写return语句,否则函数默认返回undefined。
示例3里的箭头函数用了{},但没有写return,所以每次迭代时,回调函数都返回undefined。reduce每次把undefined和下一个amount.price相加,最终结果自然是undefined。
正确的省略return写法应该去掉大括号:
const total = items.reduce((total, amount) => total + amount.price, 0);
内容的提问来源于stack exchange,提问作者Jason

