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

老规矩,上MDN:reduce-MDN

简略介绍一下一些重要的点

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

示例:

const array1 = [1, 2, 3, 4];const reducer = (accumulator, currentValue) => accumulator + currentValue;// 1 + 2 + 3 + 4console.log(array1.reduce(reducer));// expected output: 10// 5 + 1 + 2 + 3 + 4console.log(array1.reduce(reducer, 5));// expected output: 15

reducer 函数接管4个参数:

Accumulator (acc) (累计器)CurrentValue (cur) (以后值)CurrentIndex (idx) (以后索引)SourceArray (src) (源数组)

您的 reducer 函数的返回值调配给累计器,该返回值在数组的每个迭代中被记住,并最初成为最终的单个后果值

arr.reduce(callback(accumulator, currentValue, index, array), initialValue)

callback执行数组中每个值 (如果没有提供 initialValue则第一个值除外)的函数,蕴含四个参数:

`accumulator`:累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或`initialValue`。`currentValue`:数组中正在解决的元素。`index`(可选):数组中正在解决的以后元素的索引。 如果提供了`initialValue`,则起始索引号为0,否则从索引1起始。`array`(可选):调用`reduce()`的数组

reduce为数组中的每一个元素顺次执行callback函数,不包含数组中被删除或从未被赋值的元素,承受四个参数:

  • accumulator 累计器
  • currentValue 以后值
  • currentIndex 以后索引
  • array 数组

回调函数第一次执行时,accumulatorcurrentValue的取值有两种状况:
1、如果调用reduce()时提供了initialValueaccumulator取值为initialValuecurrentValue取数组中的第一个值;
2、如果没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值。

留神:官网举荐在reduce应用时提供 initialValue,为了防止谬误,更多的具体了解请查阅MDN,上面就用理论的例子来玩儿一下

1、根底的累加累乘

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

2、对象内的操作

var result = [    {        subject: 'math',        score: 10    },    {        subject: 'chinese',        score: 20    },    {        subject: 'english',        score: 30    }];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 = [[0, 1], [2, 3], [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',        age: 18    }}let fn2 = () => {    return {        name: 'lbb',        age: 19    }}let fn3 = () => {    return {        name: 'whh',        age: 20    }}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洋葱模型

// 每个中间件都能接管到corefunction 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    },    dispatch: arg => {        console.log(`我是外围操作,参数=${arg}`)    }}function receiveMiddleware(middlewareList) {    //拿到中间件队列    let dispatch = store.dispatch    let middlewareAPI = {        dispatch: arg => {            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)