Array Reduce函数疑问:为何两个看似等价的函数返回不同对象?
为什么自定义的reduce统计元素出现次数函数返回全0结果?
我来帮你理清楚这两个reduce函数的差异,问题出在条件判断的逻辑和赋值时机上,咱们一步一步拆解来看:
先把你的代码贴出来方便对照:
const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck']; // 正确的统计函数 const transportation = data.reduce((obj, item) => { if (!obj[item]) { obj[item] = 0; } obj[item]++; return obj; }, {}); console.log(transportation); // {car: 5, truck: 3, bike: 2, walk: 2, van: 2} // 出现问题的函数 var instances = data.reduce((totalObj, item) => { if (totalObj[item]) { totalObj[item]++; } else { totalObj[item] = 0; } return totalObj; }, {}); console.log(instances); // {car: 0, truck: 0, bike: 0, walk: 0, van: 0}
先看正确函数的执行逻辑(以第一次遇到car为例)
- 初始时
obj是空对象,obj['car']为undefined - 进入
if (!obj[item])判断:!undefined是true,所以执行obj['car'] = 0 - 紧接着执行
obj['car']++,把0变成1,正确记录了第一次出现的次数 - 之后再遇到
car时,obj['car']已经是1(非undefined、非0),!obj[item]为false,跳过if块直接执行累加,次数自然越来越多
再看有问题的函数的执行逻辑(同样以第一次遇到car为例)
- 初始时
totalObj['car']是undefined - 进入
if (totalObj[item])判断:undefined在布尔判断中是false,所以走else块,执行totalObj['car'] = 0 - 这里没有后续的累加操作,第一次出现就只存了0
- 第二次遇到
car时,totalObj['car']是0,0在布尔判断中也是false,依然走else块把它设为0 - 循环往复,不管遇到多少次元素,每次都会覆盖成0,最终所有计数都是0
怎么修正第二个函数?
你只需要把else里的赋值改成1就行,因为第一次遇到元素时,它的出现次数本来就是1:
var instances = data.reduce((totalObj, item) => { if (totalObj[item]) { totalObj[item]++; } else { totalObj[item] = 1; // 这里从0改成1 } return totalObj; }, {}); console.log(instances); // 现在就能得到正确结果:{car: 5, truck: 3, bike: 2, walk: 2, van: 2}
或者也可以调整条件判断逻辑,和第一个函数对齐——核心都是第一次遇到元素时先初始化基础值,然后统一执行累加操作。
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

