js数组reduce方法在项目中的实用

JavaScript中循环数组除了有for循环forEachmapfiltereverysome等外还有一个非常好用的reduce

reduce会循环数组中的每一项,在循环过程中我们可以对根据需要对任意一项进行处理,并返回处理后的数据,循环结束后reduce会将之前返回的数据进行汇总,最终我们只得到一个结果。有点类似于map方法,但map只能返回一个数组,而reduce可以返回任意类型的数据

reduce用法:

// 没有初始值
let res = arr.reduce((res, item, index, arr) => {
    ...
});

/* 传递一个初始值。传递的初始值的数据类型是什么,reduce最后得到的结果的数据类型就是什么
    此处 res2 变量的结果是一个对象
*/
let res2 = arr.reduce((res, item, index, arr) => {
    ...
}, {});

1、计算数组中所有数字的和

let arr = [10,55.9,21,0.1,3,8];

let res = arr.reduce((res, item) => {
  // 由于没有给初始值,第一次循环的时候 res 为undefined
  let sum = (typeof res === 'undefined') ? (0 + item) : res + item;
  // 这里一定要将结果return出去,否则后面的循环中res就为undefined了
  return sum;
});
console.log('res', res); // 输出结果为:98

2、计算总分数

这题与第1题基本上是相似的,但在实际工作中这题的情况比较多

let arr = [
  {subject: '语文', score: 90},
  {subject: '数学', score: 80},
  {subject: '英语', score: 78}
];
// 这里一定要给个初始值,否则res为当前循环项
let res = arr.reduce((res, item) => {
  let score = item.score;
  let sum = res + score;
  
  return sum;
}, 0);
console.log(res); // 248

3、统计数组中重复字母出现的次数

let arr = ['a','e','b','a','c','d','d','e'];
let res = arr.reduce((res, item) => {
  // 由于传递了初始值,所以第1次循环的时候res就是一个object,不会为undefined
  if(item in res){
    res[item] = res[item] + 1;
  }else{
    res[item] = 1;
  }
  /*
    {
      a: 2,
      e: 2,
      b: 1,
      c: 1,
      d: 2
    }
  */
  return res;
}, {});
console.log(res);

4、多个异步变同步执行(2020-06-19)

在ES6时代我们可以很方便的使用promise,在不使用Promise.all的情况下如何使多个promise同步执行呢?
比如我们有3个接口,A、B、C,它们的依赖关系是C->B->A,在不使用Promise.all的情况下如何才能达到Promise.all的效果?
请看下面代码

// 获取产品列表
function getProductList() {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('getProductList');
      let productList = [
        {id: '1', name: '华为P30'},
        {id: '2', name: '华为P30 Pro'}
      ];
      resolve(productList[0].id);
    }, 1000);
  });
}
// 根据产品id获取产品详情
function getProductInfo(pid) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('getProductInfo', pid);
      let product = {
        id: '1',
        name: '华为P30',
        price: 3500,
        cid: 'c_1'
      };
      resolve(product.cid);
    }, 700);
  });
}
// 获取产品的父分类
function getProductParentCategory(cid) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('getProductParentCategory', cid);
      resolve({
        id: 'c_1',
        cname: '高端手机'
      });
    }, 300);
  });
}

/**
 * 组合promise
 * @param promises
 * @returns {function(...[*]=)}
 */
function composePromise(...promises) {
  let res = function() {
    return promises.reduce((res, item) => {
      return res.then(item);
    }, Promise.resolve());
  }
  return res();
}

composePromise(getProductList, getProductInfo, getProductParentCategory)
  .then(res => {
    console.log('三个promise执行结束了');
    console.log('父分类',res);
  })
  .catch(err => {
    console.error(err);
  });

5、扁平化数组-任意深度(2020-07-29)

let arr = [1, [2, {name: '张三'}, 3, [4, 5, [6, 7, [8,9]]]]];

这样的一个未知深度的多维数组要求转成一维数组你会怎么做?
如果可以使用ES6那么我们可以使用ES的flat()函数来解决,arr.flat(Infinity)只需要这么一行代码就搞定了,但如果不允许使用的话我们也可以有多种解决方式,其中就可以使用reduce()函数
废话不多说,直接上代码

let arr = [1, [2, {name: '张三'}, 3, [4, 5, [6, 7, [8,9]]]]];
// 扁平化数组
function flat(arr){
  return arr.reduce(function (res, item){
    if(({}).toString.call(item) === '[object Array]'){
      ([]).push.apply(res, flat(item));
    }else{
      res.push(item);
    }
    return res;
  }, []);
};
// [1,2,{"name":"张三"},3,4,5,6,7,8,9]
console.log(flat(arr));
// [1,2,{"name":"张三"},3,4,5,6,7,8,9]
console.log(arr.flat(Infinity));
1.3k 声望
27 粉丝
0 条评论
推荐阅读
手把手教你vue组件库共享组件不直接打包进代码
比如你写了一个组件库,里面有Button、Dialog、MessageBox3个组件,其中Dialog、MessageBox组件都引用了Button组件,那么Button组件就是共享组件。当对这3个组件挨个打包完成后去查看Dialog、MessageBox组件打包...

heath_learning阅读 890

从零搭建 Node.js 企业级 Web 服务器(零):静态服务
过去 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面支撑业务团队开发各类业务系统,另一方面在自己的技术团队做基础技术建设。期间借着 Node.js 的锋芒做了不少 Web 系统,有的至今生气蓬勃、有的早已夭折...

乌柏木150阅读 12.3k评论 10

正则表达式实例
收集在业务中经常使用的正则表达式实例,方便以后进行查找,减少工作量。常用正则表达式实例1. 校验基本日期格式 {代码...} {代码...} 2. 校验密码强度密码的强度必须是包含大小写字母和数字的组合,不能使用特殊...

寒青56阅读 7.9k评论 11

JavaScript有用的代码片段和trick
平时工作过程中可以用到的实用代码集棉。判断对象否为空 {代码...} 浮点数取整 {代码...} 注意:前三种方法只适用于32个位整数,对于负数的处理上和Math.floor是不同的。 {代码...} 生成6位数字验证码 {代码...} ...

jenemy46阅读 6k评论 12

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木66阅读 6.2k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs39阅读 6.3k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木44阅读 7.4k评论 6

1.3k 声望
27 粉丝
宣传栏