reduce方法高级使用

前端人

共 11442字,需浏览 23分钟

 ·

2021-03-20 16:24

原文:https://segmentfault.com/a/1190000039657107


关注公众号 前端人,回复“加群

添加无广告优质学习群


前端小伙伴儿应该都听过reduce这个数组的方法,总结一下我在开发过程中遇到的reduce的一些好玩儿的用法

定义:

reduce() 方法对数组中的每个元素执行一个由您提供的 reducer 函数(升序执行),将其结果汇总为单个返回值。

reducer 函数接收4个参数:

  • Accumulator (acc) (累计器)
  • CurrentValue (cur) (当前值)
  • CurrentIndex (idx) (当前索引)
  • SourceArray (src) (源数组)

1、基础的累加累乘

var  arr = [1234];
var sum = arr.reduce((prev, cur) => prev + cur, 0)
var mul = arr.reduce((prev, cur) => prev * cur, 1)
console.log(sum); //    10
console.log(mul); //    24

2、对象内的操作

var result = [
    {
        subject'math',
        score10
    },
    {
        subject'chinese',
        score20
    },
    {
        subject'english',
        score30
    }
];

var sum = result.reduce((prev, cur) => {
    return cur.score + prev;
}, 0);
console.log(sum) //60

3、统计数组中元素出现次数

let names = ['Alice''Bob''Tiff''Bruce''Alice'];

let nameNum = names.reduce((prev, cur)=>{
  if(cur in prev){
    prev[cur]++
  }else{
    prev[cur] = 1 
  }
  return pre
}, {})
console.log(nameNum); 
//{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}

4、数组去重

let arr = [1,2,3,4,4,1]
let newArr = arr.reduce((prev, cur)=>{
    if(!prev.includes(cur)){
      return prev.concat(cur)
    }else{
      return prev
    }
}, [])
console.log(newArr);// [1, 2, 3, 4]

5、多维数组降一维数组

let arr = [[01], [23], [4,[5,6,7]]]
const newArr = function(arr){
   return arr.reduce((prev, cur) => prev.concat(Array.isArray(cur) ? newArr(cur) : cur), [])
}
console.log(newArr(arr)); 
//[0, 1, 2, 3, 4, 5, 6, 7]

6、数组和对象深克隆

const deepClone = param => {
    if (typeof param !== 'object'return
    if (Array.isArray(param)) {
        param.reduce((prev, cur) => (cur instanceof Array ? [...prev, deepClone(cur)] : [...prev, cur]), [])
    } else {
        Object.entries(param).reduce(
            (prev, [key, value]) => (typeof value === 'object' ? { ...prev, [key]: deepClone(value) } : { ...prev, [key]: value }),
            {}
        )
    }
    return param
}

7、封装一个同步顺序执行函数,并返回结果

let fn1 = () => {
    return {
        name'lsd',
        age18
    }
}
let fn2 = () => {
    return {
        name'lbb',
        age19
    }
}
let fn3 = () => {
    return {
        name'whh',
        age20
    }
}

let fnlist = [fn1, fn2, fn3]

let res = fnlist.reduce((prev, cur) => {
    let t = cur()
    if (t) {
        prev.push(t)
    }
    return prev
}, [])
console.log(res)

8、基于7封装异步请求顺序执行,并处理请求结果

let fn1 = () => {
    return new Promise((resolve, reject) => resolve(1))
}
let fn2 = () => {
    return new Promise((resolve, reject) => reject())
}
let fn3 = () => {
    return new Promise((resolve, reject) => resolve(2))
}
let fnlist = [fn1, fn2, fn3]
 let res = fnlist.reduce((prev, cur) => {
    cur().then(
        data => {
            if (data) {
                prev.push(data)
            }
        },
        reason => {
            prev.push('失败')
        }
    )
    return prev
}, [])
console.log(res)

应该在then函数中定义onResolve和onRejct函数,如果使用catch捕获错误,会进入下一次事件循环,不是同步执行;此处如果需要异步执行,请自行修改

9、模拟koa洋葱模型

每个中间件都能接收到core

function receiveMiddleware(middlewareList{
    //将中间件队列改造为函数层层嵌套形式
    //[a,b,c,d] => a(b(c(d(core)))) By reduce
    let tiggerPipe = middlewareList.reduce((a, b) => core => a(b(core)))

    let tiggerPipeWitchCore = tiggerPipe(() => {
        console.log('我是核心操作')
    })

    return tiggerPipeWitchCore
}
const VerfiyCsrfToekn = next => lastMDarg => {
    console.log('验证csrf Token')

    next(lastMDarg)

    console.log('验证csrf Token end')
}

const VerfiyAuth = next => lastMDarg => {
    console.log('验证是否登录')

    next(lastMDarg)

    console.log('验证是否登录 end')
}

const VerfiyRoutes = next => lastMDarg => {
    console.log('验证路由匹配')

    next(lastMDarg)

    console.log('验证路由匹配 end')
}
let dispatch = receiveMiddleware([VerfiyCsrfToekn, VerfiyAuth, VerfiyRoutes])
dispatch()

10、带异步控制的中间件

const store = {
    status: { name'固态空气' },
    getState() => {
        return this.status
    },
    dispatcharg => {
        console.log(`我是核心操作,参数=${arg}`)
    }
}

function receiveMiddleware(middlewareList{
    //拿到中间件队列
    let dispatch = store.dispatch
    let middlewareAPI = {
        dispatcharg => {
            dispatch(arg)
        },
        getState: store.getState
    }

    //判断中间件数量
    if (middlewareList.length === 0) {
        return dispatch
    }
    //将核心操作当作参数赋予每个中间件
    middlewareList = middlewareList.map(middleware => middleware(middlewareAPI))
    //将中间件队列改造为函数层层嵌套形式
    //[a,b,c,d] => a(b(c(d(core)))) By reduce
    let tiggerPipe = middlewareList.reduce((prev, cur) => reallyDispatch => prev(cur(reallyDispatch)))

    //重写dispatch
    dispatch = tiggerPipe(store.dispatch)
    return dispatch
}

const VerfiyCsrfToekn = middlewareAPI => next => lastMDarg => {
    console.log('验证csrf Token')
    next(lastMDarg)
    console.log('验证csrf Token end')
}

const VerfiyAuth = middlewareAPI => next => lastMDarg => {
    console.log('验证是否登录')
    next(lastMDarg)
    console.log('验证是否登录 end')
}

const VerfiyRoutes = middlewareAPI => next => lastMDarg => {
    console.log('验证路由匹配')
    next(lastMDarg)
    console.log('验证路由匹配 end')
}

const asyncMiddleware = middlewareAPI => next => lastMDarg => {
    console.log('异步中间件-start')
    if (typeof lastMDarg === 'function') {
        lastMDarg(middlewareAPI)
    } else {
        next(lastMDarg)
        console.log('异步中间件-end')
    }
}

let dispatch = receiveMiddleware([VerfiyCsrfToekn, VerfiyAuth, VerfiyRoutes, asyncMiddleware])

let asyncFun = middlewareAPI => {
    setTimeout(() => {
        let test = '我是固态空气'
        middlewareAPI.dispatch(test)
        console.log(middlewareAPI.getState())
    }, 3000)
}

dispatch(asyncFun)
javascriptes6


  • 回复资料包领取我整理的进阶资料包
  • 回复加群,加入前端进阶群
  • console.log("点赞===看===你我都快乐")
  • Bug离我更远了,下班离我更近了

浏览 24
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报