Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

JavaScript array reduce always doesn't know how to use it.

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

JavaScript数组reduce总是不会用该怎么办,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

相信不少初学者曾经都被 JavaScript 数组的 reduce方法困扰过,一直搞不明白到底怎么用。reduce方法是按顺序对数组每个元素执行某个函数,这个函数接收上一次执行结果作为参数,并将结果传给下一次调用。reduce方法用得好可以简化复杂的逻辑,提高代码可读性。通过下面几个例子可以帮你快速理解reduce的用法。

1.数字数组求和

这是reduce最常见的入门级例子。如果用传统的for循环是这样的:

function sum(arr) { let sum = 0; for (const val of arr) { sum += val; } return sum; } sum([1, 3, 5, 7]); // 16

如果用 reduce():

function sum(arr) { const reducer = (sum, val) => sum + val; const initialValue = 0; return arr.reduce(reducer, initialValue); } sum([1, 3, 5, 7]); // 16

reduce()函数的第一个参数是一个reducer函数,第二个参数是初始值。在每个数组元素上执行reducer函数,第一个参数是"累进值"。累进值的初始值是initialValue,并且在每一轮调用后更新为reducer函数的返回值。

为了帮助理解,可以用for循环实现一个简单的reduce()函数:

function reduce(arr, reducer, initialValue) { let accumulator = initialValue; for (const val of array) { accumulator = reducer(accumulator, val); } return accumulator; }

2.对象数组数字属性值求和

单看 reduce() 本身,大家更多的感受是它的晦涩难懂,而不是有多好用。如果仅仅是为了给数字数组求和,用for循环可能来得更直观。但是,当你把它跟其他数组方法(比如filter和map)结合使用时,才能感受到它的强大和方便。

举个栗子,假设有个对象数组,每个对象都有个total属性。对这些total求和:

const lineItems = [ { description: 'Eggs (Dozen)', quantity: 1, price: 3, total: 3 }, { description: 'Cheese', quantity: 0.5, price: 5, total: 2.5 }, { description: 'Butter', quantity: 2, price: 6, total: 12 } ];

用reduce可以这样写:

lineItems.reduce((sum, li) => sum + li.total, 0); // 17.5

这样是能得到最终结果,但是代码的可组合性就没那么好,可以做些优化,把total属性提前提取出来:

lineItems.map(li => li.total).reduce((sum, val) => sum + val, 0);

第二种方式为什么更好?因为这样就可以把求和的逻辑抽象到一个单独的函数sum()中,方便以后重用。

//汇总 total lineItems.map(li => li.total).reduce(sumReducer, 0); // 汇总 quantity lineItems.map(li => li.quantity).reduce(sumReducer, 0); function sumReducer(sum, val) { return sum + val; }

这种抽象比较重要,因为你觉得 sumReducer() 逻辑不会变,其实不然。比如,这个求和逻辑并没有考虑到0.1 + 0.2 !== 0.3的问题。(参考 为什么 0.1 + 0.2 = 0.300000004)如果有了这个抽象,要修复这个缺陷就比较方便了。比如:

const { round } = require('lodash'); function sumReducer(sum, val) { // 保留2位小数 return _.round(sum + val, 2); }

3.求最大值

reduce()通常用来求和,但它的功能远不止这个。累进值accumulator 可以是任意值:数字,null,undefined,数组,对象等。

举个栗子,假设有个日期数组,要找出最近的一个日期:

const dates = [ '2019/06/01', '2018/06/01', '2020/09/01', // 这个是最近日期,但是怎么找到它? '2018/09/01' ].map(v => new Date(v));

一种方法是给数组排序,找最后一个值。看上去可行,但是效率没那么高,并且用数组的默认方法给日期对象排序其实是有点小问题的。不只是日期对象,任何类型的值在sort()方法中比较,都会默认先转成字符串比较,最终结果可能并不是你想要的。

const a = [4,1,13,2]; // 惊不惊喜,意不意外? a.sort(); // [1, 13, 2, 4]

这里就可以用reduce()来处理:

// 这里是用 `>` 和` d > max ? d : max, dates[0]);

4.分组计数

假设有个对象数组,每个对象上有个age属性:

const characters = [ { name: 'Tom', age: 59 }, { name: 'Jack', age: 29 }, { name: 'Bruce', age: 29 } ];

怎样返回一个对象,包含每个age的人物角色数量?比如这样: { 29: 2, 59: 1 }.

用 reduce() 的实现方式如下:

const reducer = (map, val) => { map[val] = map[val] || 1; ++map[val]; return map; }; characters.map(char => char.age).reduce(reducer, {});

5.Promise 动态链式调用

假设你有一个异步函数数组,想要按顺序执行:

const functions = [ async function() { return 1; }, async function() { return 2; }, async function() { return 3; } ];

如果是静态的Promise代码,我们直接在代码里链式调用就行了。但如果是动态的Promise数组,可以用reduce串起来:

// 最后 `res`的结果等价于`Promise.resolve().then(fn1).then(fn2).then(fn3)` const res = await functions. reduce((promise, fn) => promise.then(fn), Promise.resolve()); res; // 3

当然,reduce 能做的事情还有很多,它本质上是对数组元素执行某种"累进"操作,最终返回单个值。

关于JavaScript数组reduce总是不会用该怎么办问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report