js数组方法reduce经典用法代码分享
以下是个人在工作中收藏总结的一些关于javascript数组方法reduce的相关代码片段,后续遇到其他使用这个函数的场景,将会陆续添加,这里作为备忘。
javascript数组那么多方法,为什么我要单挑reduce方法,一个原因是我对这个方法掌握不够,不能够用到随心所欲。另一个方面,我也感觉到了这个方法的庞大魅力,在许多的场景中发挥着神奇的作用。
理解reduce函数
reduce()方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值。
arr.reduce([callback,initialValue])
看如下例子:
letarr=[1,2,3,4,5];
//10代表初始值,p代表每一次的累加值,在第一次为10
//如果不存在初始值,那么p第一次值为1
//此时累加的结果为15
letsum=arr.reduce((p,c)=>p+c,10);//25
//转成es5的写法即为:
varsum=arr.reduce(function(p,c){
console.log(p);
returnp+c;
},10);
片段一:字母游戏
constanagrams=str=>{
if(str.length<=2){
returnstr.length===2?[str,str[1]+str[0]]:str;
}
returnstr.split("").reduce((acc,letter,i)=>{
returnacc.concat(anagrams(str.slice(0,i)+str.slice(i+1)).map(val=>letter+val));
},[]);
}
anagrams("abc");//结果会是什么呢?
reduce负责筛选出每一次执行的首字母,递归负责对剩下字母的排列组合。
片段二:累加器
constsum=arr=>arr.reduce((acc,val)=>acc+val,0); sum([1,2,3]);
片段三:计数器
constcountOccurrences=(arr,value)=>arr.reduce((a,v)=>v===value?a+1:a+0,0); countOccurrences([1,2,3,2,2,5,1],1);
循环数组,每遇到一个值与给定值相等,即加1,同时将加上之后的结果作为下次的初始值。
片段四:函数柯里化
函数柯里化的目的就是为了储存数据,然后在最后一步执行。
constcurry=(fn,arity=fn.length,...args)=> arity<=args.length?fn(...args):curry.bind(null,fn,arity,...args); curry(Math.pow)(2)(10); curry(Math.min,3)(10)(50)(2);
通过判断函数的参数取得当前函数的length(当然也可以自己指定),如果所传的参数比当前参数少,则继续递归下面,同时储存上一次传递的参数。
片段五:数组扁平化
constdeepFlatten=arr=> arr.reduce((a,v)=>a.concat(Array.isArray(v)?deepFlatten(v):v),[]); deepFlatten([1,[2,[3,4,[5,6]]]]);
片段六:生成菲波列契数组
constfibonacci=n=>Array(n).fill(0).reduce((acc,val,i)=>acc.concat(i>1?acc[i-1]+acc[i-2]:i),[]); fibonacci(5);
片段七:管道加工器
constpipe=(...funcs)=>arg=>funcs.reduce((acc,func)=>func(acc),arg);
pipe(btoa,x=>x.toUpperCase())("Test");
通过对传递的参数进行函数加工,之后将加工之后的数据作为下一个函数的参数,这样层层传递下去。
片段八:中间件
constdispatch=action=>{
console.log('action',action);
returnaction;
}
constmiddleware1=dispatch=>{
returnaction=>{
console.log("middleware1");
constresult=dispatch(action);
console.log("aftermiddleware1");
returnresult;
}
}
constmiddleware2=dispatch=>{
returnaction=>{
console.log("middleware2");
constresult=dispatch(action);
console.log("aftermiddleware2");
returnresult;
}
}
constmiddleware3=dispatch=>{
returnaction=>{
console.log("middleware3");
constresult=dispatch(action);
console.log("aftermiddleware3");
returnresult;
}
}
constcompose=middlewares=>middlewares.reduce((a,b)=>args=>a(b(args)))
constmiddlewares=[middleware1,middleware2,middleware3];
constafterDispatch=compose(middlewares)(dispatch);
consttestAction=arg=>{
return{type:"TEST_ACTION",params:arg};
};
afterDispatch(testAction("1111"));
redux中经典的compose函数中运用了这种方式,通过对中间件的重重层叠,在真正发起action的时候触发函数执行。 片段九:redux-actions对state的加工片段
//redux-actions/src/handleAction.js
consthandleAction=(type,reducer,defaultState)=>{
consttypes=type.toString();
const[nextReducer,throwReducer]=[reducer,reducer];
return(state=defaultState,action)=>{
const{type:actionType}=action;
if(!actionType||types.indexOf(actionType.toString())===-1){
returnstate;
}
return(action.error===true?throwReducer:nextReducer)(state,action);
}
}
//reduce-reducers/src/index.js
constreduceReducer=(...reducers)=>{
return(previous,current)=>{
reducers.reduce((p,r)=>r(p,current),previous);
}
}
//redux-actions/src/handleActions.js
consthandleActions=(handlers,defaultState,{namespace}={})=>{
//reducers的扁平化
constflattenedReducerMap=flattenReducerMap(handles,namespace);
//每一种ACTION下对应的reducer处理方式
constreducers=Reflect.ownkeys(flattenedReducerMap).map(type=>handleAction(
type,
flattenedReducerMap[type],
defaultState
));
//状态的加工器,用于对reducer的执行
constreducer=reduceReducers(...reducers);
//reducer触发
return(state=defaultState,action)=>reducer(state,action);
}
片段十:数据加工器
constreducers={
totalInEuros:(state,item)=>{
returnstate.euros+=item.price*0.897424392;
},
totalInYen:(state,item)=>{
returnstate.yens+=item.price*113.852;
}
};
constmanageReducers=reducers=>{
return(state,item)=>{
returnObject.keys(reducers).reduce((nextState,key)=>{
reducers[key](state,item);
returnstate;
},{})
}
}
constbigTotalPriceReducer=manageReducers(reducers);
constinitialState={euros:0,yens:0};
constitems=[{price:10},{price:120},{price:1000}];
consttotals=items.reduce(bigTotalPriceReducer,initialState);
片段十一:对象空值判断
letschool={
name:'Hopemiddleschool',
created:'2001',
classes:[
{
name:'三年二班',
teachers:[
{name:'张二蛋',age:26,sex:'男',actor:'班主任'},
{name:'王小妞',age:23,sex:'女',actor:'英语老师'}
]
},
{
name:'明星班',
teachers:[
{name:'欧阳娜娜',age:29,sex:'女',actor:'班主任'},
{name:'李易峰',age:28,sex:'男',actor:'体育老师'},
{name:'杨幂',age:111,sex:'女',actor:'艺术老师'}
]
}
]
};
//常规做法
school.classes&&
school.classes[0]&&
school.classes[0].teachers&&
school.classes[0].teachers[0]&&
school.classes[0].teachers[0].name
//reduce方法
constget=(p,o)=>p.reduce((xs,x)=>(xs&&xs[x]?xs[x]:null),o);
get(['classes',0,'teachers',0,'name'],school);//张二蛋
片段十二:分组
constgroupBy=(arr,func)=>
arr.map(typeoffunc==='function'?func:val=>val[func]).reduce((acc,val,i)=>{
acc[val]=(acc[val]||[]).concat(arr[i]);
returnacc;
},{});
groupBy([6.1,4.2,6.3],Math.floor);
groupBy(['one','two','three'],'length');
首先通过map计算出所有的键值,然后再根据建值进行归类
片段十三:对象过滤
constpick=(obj,arr)=>
arr.reduce((acc,curr)=>(currinobj&&(acc[curr]=obj[curr]),acc),{});pick({a:1,b:'2',c:3},['a','c']);
constremove=(arr,func)=>
Array.isArray(arr)
?arr.filter(func).reduce((acc,val)=>{
arr.splice(arr.indexOf(val),1);
returnacc.concat(val);
},[]):[];
constarr=[1,2,3,4];
remove(arr,n=>n%2==0);
construnPromisesInSeries=ps=>ps.reduce((p,next)=>p.then(next),Promise.resolve());
constdelay=d=>newPromise(r=>setTimeout(r,d));
constprint=args=>newPromise(r=>r(args));
runPromisesInSeries([()=>delay(1000),()=>delay(2000),()=>print('hello')]);
constorderBy=(arr,props,orders)=>
[...arr].sort((a,b)=>
props.reduce((acc,prop,i)=>{
if(acc===0){
const[p1,p2]=orders&&orders[i]==='desc'?[b[prop],a[prop]]:[a[prop],b[prop]];
acc=p1>p2?1:p1
片段十七:选择
constselect=(from,selector)=>
selector.split('.').reduce((prev,cur)=>prev&&prev[cur],from);
constobj={selector:{to:{val:'valtoselect'}}};
select(obj,'selector.to.val');
以上就是我们为大家整理的关于js数组方法reduce经典用法代码内容,感谢你对毛票票的支持。