前端小夥伴兒應該都聽過reduce這個數組的方法,總結一下我在開發過程當中遇到的reduce的一些好玩兒的用法前端
老規矩,上MDN:reduce-MDN數組
簡單介紹一下一些重要的點koa
定義:reduce()
方法對數組中的每一個元素執行一個由您提供的 reducer
函數(升序執行),將其結果彙總爲單個返回值。異步
示例:async
const array1 = [1, 2, 3, 4]; const reducer = (accumulator, currentValue) => accumulator + currentValue; // 1 + 2 + 3 + 4 console.log(array1.reduce(reducer)); // expected output: 10 // 5 + 1 + 2 + 3 + 4 console.log(array1.reduce(reducer, 5)); // expected output: 15
reducer
函數接收4個參數:函數
Accumulator (acc) (累計器) CurrentValue (cur) (當前值) CurrentIndex (idx) (當前索引) SourceArray (src) (源數組)
您的 reducer
函數的返回值分配給累計器,該返回值在數組的每一個迭代中被記住,並最後成爲最終的單個結果值this
arr.reduce(callback(accumulator, currentValue, index, array), initialValue)
callback
執行數組中每一個值 (若是沒有提供 initialValue則第一個值除外
)的函數,包含四個參數:spa
`accumulator`:累計器累計回調的返回值; 它是上一次調用回調時返回的累積值,或`initialValue`。 `currentValue`:數組中正在處理的元素。 `index`(可選):數組中正在處理的當前元素的索引。 若是提供了`initialValue`,則起始索引號爲0,不然從索引1起始。 `array`(可選):調用`reduce()`的數組
reduce
爲數組中的每個元素依次執行callback
函數,不包括數組中被刪除或從未被賦值的元素,接受四個參數:code
accumulator 累計器
currentValue 當前值
currentIndex 當前索引
array 數組
回調函數第一次執行時,accumulator
和currentValue
的取值有兩種狀況:
一、若是調用reduce()
時提供了initialValue
,accumulator
取值爲initialValue
,currentValue
取數組中的第一個值;
二、若是沒有提供 initialValue
,那麼accumulator
取數組中的第一個值,currentValue
取數組中的第二個值。csrf
注意:官方推薦在reduce使用時提供 initialValue
,爲了不錯誤,更多的詳細理解請查閱MDN,下面就用實際的例子來玩兒一下
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); // 10 console.log(mul); // 24
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
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}
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]
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]
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 }
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)
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捕獲錯誤,會進入下一次事件循環,不是同步執行;此處若是須要異步執行,請自行修改
// 每一箇中間件都能接收到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()
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)