Js中函数式编程的理解 (4)

函数组合的目的是将多个函数组合成一个函数,写一个简单的示例。

const compose = (f, g) => x => f(g(x)); const f = x => x + 1; const g = x => x * 2; const fg = compose(f, g); fg(1) //3

我们可以看到compose就实现了一个简单的功能,形成了一个全新的函数,而这个函数就是一条从g -> f的流水线,同时我们可以很轻易的发现compose其实是满足结合律的。

compose(f, compose(g, t)) <=> compose(compose(f, g), t) <=> f(g(t(x)));

只要其顺序一致,最后的结果是一致的,因此我们可以写个更高级的compose,支持多个函数组合。

const compose = (...fns) => (...args) => fns.reduceRight((params, fn) => [fn.apply(null, [].concat(params))], args).pop(); const f = x => x + 1; const g = x => x * 2; const t = (x, y) => x + y; let fgt = compose(f, g, t); console.log(fgt(1, 2)); // 7 // 3 -> 6 -> 7

现在我们考虑一个小需求,将数组最后一个元素大写,假设log、head、reverse、toUpperCase函数存在,之后以命令式的写法是:

log(toUpperCase(head(reverse(arr))))

面向对象的写法:

arr.reverse() .head() .toUpperCase() .log()

链式调用看起来顺眼多了,通过函数组合组合的写法:

const upperLastItem = compose(log, toUpperCase, head, reverse);

这其实就是类似于所谓管道pipe的概念,在Linux命令中常会用到,类似ps grep的组合,只是管道的执行方向和compose的(从右往左组合好像刚好相反,因此很多函数库Lodash、Ramda等中也提供了另一种组合方式pipe。

const upperLastItem = R.pipe(reverse, head, toUppderCase, log);

那么最终,我们回到一开始的那个例子,将其完成为一个能跑通的示例。

const compose = (...fns) => (...args) => fns.reduceRight((params, fn) => [fn.apply(null, [].concat(params))], args).pop(); const curry = function(funct, ...args) { const argsLength = funct.length; return function(..._args) { _args.unshift(...args); if (_args.length < argsLength) return curry.call(this, funct, ..._args); return funct.apply(this, _args); } } const join = curry((str, arr) => arr.join(str)); const map = curry((callback, arr) => arr.map(callback)); const split = curry((gap, str) => str.split(gap)); const capitalize = x => x[0].toUpperCase() + x.slice(1).toLowerCase(); const genObj = curry((key, x) => { let obj = {}; obj[key] = x; return obj; }) const capitalizeName = compose(join(" "), map(capitalize), split("-")); const convert2Obj = compose(genObj("name"), capitalizeName); const convertName = map(convert2Obj); const result = convertName(["john-reese", "harold-finch", "sameen-shaw"]); console.log(result); /* [ { name: 'John Reese' }, { name: 'Harold Finch' }, { name: 'Sameen Shaw' } ] */ 每日一题 https://github.com/WindrunnerMax/EveryDay 参考 https://zhuanlan.zhihu.com/p/67624686 https://juejin.cn/post/6844903936378273799 https://gist.github.com/riskers/637e23baeaa92c497efd52616ca83bdc https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/ch1.html https://blog.fundebug.com/2019/08/09/learn-javascript-functional-programming/

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zydzsp.html