一文读懂JavaScript函数式编程重点-- 实践 总结
好记性不如烂笔头,有时间将JS函数式编程,在JS方面毕竟有限,如果真要学习好函数式编程,建议学习下Haskell,本文就是将关于JS方面知识点尽可能总结全面。
- 柯里化
- 偏应用
- 组合与管道
- 函子
- Monad
1. 柯里化
- 什么是柯里化呢?
柯里化是把一个多参数函数转化为一个嵌套的一元函数的过程。下面我们用介绍柯里化时候很多文章都会使用的例子,加法例子(bad smile)。
// 原始版本
const add = (x,y) => x + y;
// ES6 柯里化版本
const addCurried = x => y => x + y;
你没有看错,就是这么简单,柯里化就是将之前传入的多参数变为传入单参数,解释下,柯里化版本,其实当传入一个参数addCurried(1)时,实际会返回一个函数 y=>1+y,实际上是将add函数转化为含有嵌套的一元函数的addCurried函数。如果要调用柯里化版本,应该使用addCurried(1)(2)方式进行调用 会达到和add(1,2)一样的效果,n 个连续箭头组成的函数实际上就是柯里化了 n - 1次,前 n - 1 次调用,其实是提前将参数传递进去,并没有调用最内层函数体,最后一次调用才会调用最内层函数体,并返回最内层函数体的返回值。
看到这里感觉是不是很熟悉,没错,React 中间件。
以上是通过ES6箭头函数实现的,下面我们构建curryFn来实现这个过程。
此函数应该比较容易理解,比较函数参数以及参数列表的长度,递归调用合并参数,当参数都为3,不满足,调用fn.apply(null, args)。
例子: 使用以上的curryFn 数组元素平方函数式写法。
const curryFn = (fn) => {
if(typeof fn !== 'function'){
throw Error ('Not Function');
}
return function curriedFn(...args){
if(args.length < fn.length){
return function(){
return curriedFn.apply(null, args.concat(
[].slice.call(arguments)
))
}
}
return fn.apply(null, args);
}
}
const map = (fn, arr) => arr.map(fn);
const square = (x) => x * x;
const squareFn = curryFn(map)(square)([1,2,3])
从上例子可以观察出curryFn函数应用参数顺序是从左到右。如果想从右到左,下面一会会介绍。
2. 偏应用
上面柯里化我们介绍了我们对于传入多个参数变量的情况,如何处理参数关系,实际开发中存在一种情况,写一个方法,有些参数是固定不变的,即我们需要部分更改参数,不同于柯里化得全部应用参数。
const partial = function (fn, ...partialArgs)