由浅入深讲解数组的reduce用法

数组中的reduce犹如一只魔法棒,通过它可以做一些黑科技一样的事情。本文从api讲解到一般用法再到高级用法,由浅入深的讲一讲数组中的reduce。MDN链接

Array.prototype.reduce

reduce的api是这样的,

reduce(callback(accumulator, currentValue[, index, array])[,initialValue])
  • Callback

    • accumulator 积累的值
    • currentValue 当前值
    • index 当前下标
    • array 当前数组
  • initialValue 初始值

reduce接受两个参数,回调函数和初识值,初始值是可选的。回调函数接受4个参数:积累值、当前值、当前下标、当前数组。
如果reduce的参数只有一个,那么积累值一开始是数组中第一个值,如果reduce的参数有两个,那么积累值一开始是出入的initialValue初始值。
然后在每一次迭代时,返回的值作为下一次迭代的accumulator 积累值。

重要说明:如果未设置initialValue,那么reduce将使用您的第一个数组值作为第一次迭代的accumulator,从第二个数组元素上开始循环,从index=1开始(如果有的话)

以下是reduce的几种实际应用。

1. 将数组转化为对象

将下面的数组转成以id为key的对象。


const userList = [
    {
        id: 1,
        username: 'john',
        sex: 1,
        email: 'john@163.com'
    },
    {
        id: 2,
        username: 'jerry',
        sex: 1,
        email: 'jerry@163.com'
    },
    {
        id: 3,
        username: 'nancy',
        sex: 0,
        email: ''
    }
];

let objUserList = userList.reduce(keyByUserNameReducer, {})

function keyByUserNameReducer(acculumator, currentValue, currentIndex, array) {
    return {...acculumator, [currentValue.id]: currentValue}
}

console.log(objUserList)

// {
//    '1': { id: 1, username: 'john', sex: 1, email: 'john@163.com' },
//    '2': { id: 2, username: 'jerry', sex: 1, email: 'jerry@163.com' },
//    '3': { id: 3, username: 'nancy', sex: 0, email: '' }
// }

2. 将小数组展开成大数组

将下面数组按照逗号分割.


const fileLines = [
    'Inspector Algar,Inspector Bardle,Mr. Barker,Inspector Barton',
    'Inspector Baynes,Inspector Bradstreet,Inspector Sam Brown',
    'Monsieur Dubugue,Birdy Edwards,Inspector Forbes,Inspector Forrester',
    'Inspector Gregory,Inspector Tobias Gregson,Inspector Hill',
    'Inspector Stanley Hopkins,Inspector Athelney Jones'
];

let commaArray = fileLines.reduce(function (acculumator, currentValue, currentIndex, array) {
    return acculumator.concat(currentValue.split(/,/g))
}, [])
console.log(commaArray)
/*
[
    'Inspector Algar',
    'Inspector Bardle',
    'Mr. Barker',
    'Inspector Barton',
    'Inspector Baynes',
    'Inspector Bradstreet',
    'Inspector Sam Brown',
    'Monsieur Dubugue',
    'Birdy Edwards',
    'Inspector Forbes',
    'Inspector Forrester',
    'Inspector Gregory',
    'Inspector Tobias Gregson',
    'Inspector Hill',
    'Inspector Stanley Hopkins',
    'Inspector Athelney Jones'
  ]
*/

3. 用reduce实现flatMap


// 数组的flatMap
// flatMap的底层的操作:先使用map操作,然后对得到的数组仅展开一层再得到一个数组
const arr = ["今天天气不错", "", "早上好"];
let flatMapArr = arr.flatMap((item, index) => {
    return item.split("")
})
console.log(flatMapArr) // ['今', '天', '天','气', '不', '错','早', '上', '好']

// 使用数组的reduce实现数组的flatMap
let reduceFlatMap = arr.reduce(function (acculumator, currentValue, currentIndex, array) {
    return [...acculumator, ...currentValue.split('')]
}, [])
console.log(reduceFlatMap) // ['今', '天', '天','气', '不', '错','早', '上', '好']

4. 按顺序执行异步函数

根据userList数组的name属性去依次请求数据。


let asyncReducer = userList.reduce(async function (acculumator, currentValue, currentIndex, array) {
    const obj = await acculumator.then()
    let re = await new Promise((resolve, reject) => {
        // 用 setTimeout 模拟请求数组
        setTimeout(() => {
            resolve(`to=>${currentValue.username}`)
        }, 1000)
    })
    return {...obj, [currentValue.username]: re}

}, Promise.resolve({}))
asyncReducer.then(res => {
    console.log(res)
})

// 3s之后打印:
// { john: 'to=>john', jerry: 'to=>jerry', nancy: 'to=>nancy' }

总结:

  • 记住在处理对象数组时要指定一个initialValue
  • 数字数组使用reduce代码干净,请尽量不要把reduce函数过于复杂
  • 不要忘记在回调函数中返回,否则最后得到的值将可能出现错误
  • 回调函数的第三个参数index访问迭代次数
  • reduce处理时会跳过数组空值

justsso
学习与实践的记录者

热爱生活&前端。

57 声望
4 粉丝
0 条评论
推荐阅读
单文件组件下的vue,可以擦出怎样的火花
与时俱进吧,看着 vue3 和 vite,虽然不会用,但还是心痒痒,然后就把原先基于 vue@2 的实现做了重构。不周之处,大家见谅!下面关于过期的内容,我就用删除线标记了。

leftstick64阅读 45.2k评论 18

从零搭建 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

热爱生活&前端。

57 声望
4 粉丝
宣传栏