楔子 在JavaScript中,由于Function本质也是对象(这与Haskell中【函数的本质是值】思路一致),所以我们可以把Function作为参数来进行传递! 例:functionsayHi(){console。log(Hi);}functionsayBye(){console。log(Bye);}functiongreet(type,sayHi,sayBye){type1?sayHi():sayBye()}greet(1,sayHi,sayBye);Hi 又得讲这个老生常谈的定义:如果一个函数接收函数作为参数或返回函数作为输出,那么这个函数被称作高阶函数; 本篇要谈的是:高阶函数中的map、filter、reduce是【如何实践】的,我愿称之为:高阶映射!! 先别觉得这东西陌生,其实咱们天天都见!! 例:〔1,2,3〕。map(itemitem2)实践 Talkischeap。Showmethecode。 以下有4组代码,每组的2个代码片段实现目标一致,但实现方式有异,感受感受,你更喜欢哪个? 第1组: 1constarr1〔1,2,3〕;constarr2〔〕;for(leti0;iarr1。length;i){arr2。push(arr1〔i〕2);}console。log(arr2);〔2,4,6〕 2constarr1〔1,2,3〕;constarr2arr1。map(itemitem2);console。log(arr2);〔2,4,6〕 第2组: 1constbirthYear〔1975,1997,2002,1995,1985〕;constages〔〕;for(leti0;ibirthYear。length;i){letage2018birthYear〔i〕;ages。push(age);}console。log(ages);〔43,21,16,23,33〕 2constbirthYear〔1975,1997,2002,1995,1985〕;constagesbirthYear。map(year2018year);console。log(ages);〔43,21,16,23,33〕 第3组: 1constpersons〔{name:Peter,age:16},{name:Mark,age:18},{name:John,age:27},{name:Jane,age:14},{name:Tony,age:24},〕;constfullAge〔〕;for(leti0;ipersons。length;i){if(persons〔i〕。age18){fullAge。push(persons〔i〕);}}console。log(fullAge); 2constpersons〔{name:Peter,age:16},{name:Mark,age:18},{name:John,age:27},{name:Jane,age:14},{name:Tony,age:24},〕;constfullAgepersons。filter(personperson。age18);console。log(fullAge); 第4组: 1constarr〔5,7,1,8,4〕;letsum0;for(leti0;iarr。length;i){sumsumarr〔i〕;}console。log(sum);25 2constarr〔5,7,1,8,4〕;constsumarr。reduce(function(accumulator,currentValue){returnaccumulatorcurrentValue;});console。log(sum);25 更喜欢哪个?有答案了吗? 每组的代码片段2就是mapfilterreduce高阶函数的应用,没有别的说的,就是更加简洁易读!手写 实际上,mapfilterreduce也是基于for循环封装来的,所以我们也能自己实现一套相同的高阶映射;map1Array。prototype。map1function(fn){letnewArr〔〕;for(leti0;ithis。length;i){newArr。push(fn(this〔i〕))};returnnewArr;}console。log(〔1,2,3〕。map1(itemitem2))〔2,4,6〕filter1Array。prototype。filter1function(fn){letnewArr〔〕;for(leti0;ithis。length;i){fn(this〔i〕)newArr。push(this〔i〕);}returnnewArr;};console。log(〔1,2,3〕。filter1(itemitem2))〔3〕reduce1Array。prototype。reduce1function(reducer,initVal){for(leti0;ithis。length;i){initValreducer(initVal,this〔i〕,i,this);}returninitVal};console。log(〔1,2,3〕。reduce1((a,b)ab,0))6 如果你不想直接挂在原型链上:mapForEachfunctionmapForEach(arr,fn){constnewArray〔〕;for(leti0;iarr。length;i){newArray。push(fn(arr〔i〕));}returnnewArray;}mapForEach(〔1,2,3〕,itemitem2)〔2,4,6〕filterForEachfunctionfilterForEach(arr,fn){constnewArray〔〕;for(leti0;iarr。length;i){fn(arr〔i〕)newArray。push(arr〔i〕);}returnnewArray;}filterForEach(〔1,2,3〕,itemitem2)〔3〕reduceForEachfunctionreduceForEach(arr,reducer,initVal){constnewArray〔〕;for(leti0;iarr。length;i){initValreducer(initVal,arr〔i〕,i,arr);}returninitVal;}reduceForEach(〔1,2,3〕,(a,b)ab,0)6 这里本瓜有个小疑惑,在ES6之前,有没有一个库做过这样的封装小结 本篇虽基础,但很重要! 对一些惯用写法的审视、改变,会产生一些奇妙的思路稀松平常的map映射能做的比想象中的要多得多! for循环遍历只是操作性的手段,不是目的!而封装过后的map映射有了更易读的意义,映射关系(输入、输出)也是函数式编程之核心! YY一下:既然map这类函数都是从for循环封装来的,如果你能封装一个基于for循环的另一种特别实用的高阶映射或者其它高阶函数,是不是意味着:有朝一日有可能被纳入JS版本标准API中? 或许:先意识到我们每天都在使用的高阶函数,刻意的去使用、训练,然后能举一反三,才能做上面的想象吧我是掘金安东尼:一名人气前端技术博主(文章100w阅读量) 终身写作者(INFP写作人格) 坚持与热爱(简书打卡1000日) 我能陪你一起度过漫长技术岁月吗(以梦为马) 觉得不错,给个点赞和关注吧(这是我最大的动力)b()d