开发者每天面临的几乎所有问题都可以通过解决一个定义明确的问题的一组更小的解决方案来解决。这些解决方案最好被描述为“纯函数”。尽管这些函数中的大多数都在不同的库中实现,但了解如何以及何时将难题分解为更小的问题非常重要。这种解决问题的心态会提高我们的开发效率,让我们成为更好的开发者。在今天的文章中,我无序地分享了我经常用来解决各种问题的20个有用的“纯函数”,希望对你也有用。接下来,让我们开始吧。1.GetValue给定一个对象或数组,该函数将返回指定路径的值,否则为null。constgetValue=(obj,path)=>path.replace(/\[([^[\]]*)]/g,'.$1.').split('.').filter(prop=>prop!=='').reduce((prev,next)=>(previnstanceofObject?prev[next]:undefined),obj);getValue({a:{b:c:'d'}},'a.b.C');//=dgetValue({a:{b:c:[1,2]}},'a.b.c[1]');//=22,Clamp确保值在指定范围内,否则“钳制”到最接近的最小值和最大值。constclamp=(min,max,value)=>{if(min>max)thrownewError('min不能大于max');返回值<最小值?最小值:值>最大值?最大值:值;}}钳位(0、10、-5);//=0clamp(0,10,20);//=103.Sleep在执行下一个操作之前等待指定的持续时间(以毫秒为单位)。constsleep=async(duration)=>(newPromise(resolve=>setTimeout(resolve,duration)));等待睡眠(1000);//等待1sec4,GroupBy根据键控函数和索引对对象中的相关项进行分组。constgroupBy=(fn,list)=>(list.reduce((prev,next)=>({...prev,[fn(next)]:[...(prev[fn(next)]||[]),next]}),{}));groupBy(vehicle=>vehicle.make,[{make:'tesla',model:'3'},{make:'tesla',model:'y'},{make:'ford',model:'mach-e'},]);//{//tesla:[{make:'tesla',...},{make:'tesla',...}],//ford:[{make:'ford',...}],//}5.CollectBy根据键控函数创建包含相关项的子列表。importgroupByfrom'./groupBy';constcollectBy=(fn,list)=>Object.values(groupBy(fn,list));collectBy(vehicle=>vehicle.make,[{make:'tesla',model:'3'},{make:'tesla',model:'y'},{make:'ford',model:'mach-e'},]);//[//[{make:'tesla',...},{make:'tesla',...}],//[{make:'ford',...}],//]6.Head获取列表的第一个元素。此函数对于编写干净且可读的代码很有用。consthead=list=>list[0];head([1,2,3]);//=1head([]);//=undefined7,Tail获取列表中除第一个元素之外的所有元素。此函数对于编写干净且可读的代码很有用。consttail=list=>list.slice(1);tail([1,2,3]);//=[2,3]尾巴([]);//=[]8,Flatten递归地从嵌套子列表中提取所有项目以创建一个平面列表。constflatten=list=>list.reduce((prev,next)=>([...prev,...(Array.isArray(next)?flatten(next):[next])]),[]);展平([[1,2,[3,4],5,[6,[7,8]]]]);//=[1,2,3,4,5,6,7,8]9.IntersectionBy找到键控函数定义的两个列表中存在的所有值。constintersectionBy=(fn,listA,listB)=>{constb=newSet(listB.map(fn);returnlistA.filter(val=>b.has(fn(val)));};intersectionBy(v=>v,[1,2,3],[2,3,4]);//=[2,3]intersectionBy(v=>v,[{a:1},{a:2}],[{a:2},{a:3},{a:4}]);//=[{a:2}];10.IndexBy对列表索引中的每个元素执行key函数确定的值.constindexBy=(fn,list)=>list.reduce((prev,next)=>({...prev,[fn(next)]:next},{});indexBy(val=>val.a,[{a:1},{a:2},{a:3}]);//={1:{a:1},2:{a:2},3:{a:3}}11.DifferenceBy查找第一个列表中不存在于第二个列表中的所有项,由键控函数确定importindexByfrom'./indexBy';constdifferenceBy=(fn,listA,listB)=>{constbIndex=indexBy(fn,listb);返回listA.filter(val=>!bIndex[fn(val)]);});differenceBy(val=>val,[1,2,3],[3,4,5]);//=[1,2]differenceBy(vehicle=>vehicle.make,[{make:'tesla'},{make:'ford'},{make:'gm'}],[{make:'tesla'},{make:'bmw'},{make:'audi'}],);//=[{make:'ford'},{make:'gm'}]12,RecoverWithif如果给定的函数抛出错误,则返回默认值。constrecoverWith=async(defaultValue,fn,...args)=>{try{constresult=awaitfn(...args);返回结果;}catch(_e){返回默认值;}}recoverWith('A',val=>val,'B');//=BrecoverWith('A',()=>{thrownewError()});//='A'13,Distance计算两点p1和p2之间的距离。constdistance=([x0,y0],[x1,y1])=>(Math.hypot(x1-x0,y1-y0));距离([0,1],[5,4]);//=5.830951894845314,DropWhile从列表中删除元素,从第一个元素开始,直到满足som谓词。constdropWhile=(pred,list)=>{让索引=0;list.every(elem=>{index++;returnpred(elem);});返回list.slice(index-1);}dropWhile(val=>(val<5),[1,2,3,4,5,6,7]);//=[5,6,7]15,SumBy给定某个函数,该函数为每个元素生成一个单独的值,计算列表中所有元素的总和。constsumBy=(fn,列表)=>列表。reduce((prev,next)=>prev+fn(next),0);sumBy(product=>product.price,[{name:'pizza',price:10},{name:'pepsi',price:5},{name:'salad',price:5},]);//=2016,Ascending给定一个评估函数,创建一个升序比较器函数。constascending=(fn)=>(a,b)=>{constvalA=fn(a);constvalB=fn(b);返回valA
