目录
1、柯里化 (Currying)
当一个函数有多个参数的时候先传递一部分参数调用它(这部分参数以后永远不变)
然后返回一个新的函数接收剩余的参数,返回结果
下图示例是普通函数与柯里化函数(纯函数)的对比
//普通的函数
function checkAge (min,age) {
return age >= min
}
console.log(checkAge(18,20));
console.log(checkAge(18,24))
//高进阶纯函数(避免重复的18硬编码)
function checkAge(min){
return function(age){
return age >= min
}
}
//es6写法
//let checkAge = min => (age => age >= min);
let checkAge18 = checkAge(18);
let checkAge20 = checkAge(20);
console.log(checkAge18(20));//true
console.log(checkAge18(24))//true
2、柯里化函数的应用: _.curry(func)
功能:创建一个函数,该函数接收一个或多个 func 的参数,如果 func 所需要的参数都被提供则执行 func 并返回执行的结果。 否则继续返回该函数并等待接收剩余的参数
参数:需要柯里化的函数
//lodash中的柯里化函数 curry 使用 ,将多个函数变为一元函数
const _ = reuqire('lodash');
function getSum (a, b, c) {
return a + b + c
}
const curried = _.curry(getSum);
console.log(curried(1, 2, 3));//6
console.log(curried(1)(1, 3));//6
console.log(curried(1, 2)(3))//6
//模拟curry
function curry(func){
return function curriedFn(...args){ //表示传入的实参
if(args.length < func.length){ //实参是否小于形参
return function(){
//Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组。
//参考此博客:https://www.cnblogs.com/jf-67/p/8440758.html
return curriedFn(...args.concat(Array.from(arguments)))//将arguments伪数组转换成数组
}
}
return func(...args)
}
}
const curried1 = curry(getSum);
console.log(curried1(1, 2, 3));//6
console.log(curried1(1)(1, 3));//6
console.log(curried1(1, 2)(3))//6
3、柯里化总结
柯里化可以让我们给一个函数传递较少的参数得到一个已经记住了某些固定参数的新函数
这是一种对函数参数的'缓存'
让函数变的更灵活,让函数的粒度更小
可以把多元函数转换成一元函数,可以组合使用函数产生强大的功能
4、函数组合(compose)
如果一个函数要经过多个函数处理才能得到最终值,这个时候可以把中间过程的函数合并成一个函数。
函数就像是数据的管道,函数组合就是把这些管道连接起来,让数据穿过多个管道形成最终结果 。
函数组合默认是从右到左执行
//函数组合演示
function compose (f, g) {
return function (value){
return f(g(value))
}
}
function reverse (array) {
return array.reverse()
}
function first (array) {
return array[0]
}
const last = compose(first, reverse);
console.log(last([1, 2, 3, 4])) //4
注:此案例只是为了展示组合函数的思路,用组合函数的方式最大的好处可以重用,避免出错。
5、Lodash 组合函数
flow() 或者 flowRight(),他们都可以组合多个函数
flow() 是从左到右运行
flowRight() 是从右到左运行,使用的更多一些
//lodash 中的函数组合的方法 _.flowRight()
const _ = reuqire('lodash')
const reverse = arr => arr.reverse()
const first = arr => arr[0];
const toUpper = s => s.toUpperCase()
const f = _.flowRight(toUpper, first, reverse)
console.log(f(['one', 'two', 'three']))//THREE
//组合函数的原理模拟
//关于reduce的博客:https://www.cnblogs.com/jf-67/p/10768198.html
function compose (...args) {
return function (value) {
return args.reverse().reduce(function (acc, fn) {
return fn(acc)
}, value)
}
}
//es6 箭头函数写法
const compose = (...args) => value => args.reverse().reduce((acc,fn) => fn(acc), value)
const f = compose(toUpper, first, reverse)
console.log(f(['one', 'two', 'three']))//THREE
Lodash函数组合---结合律
//lodash 中的函数组合---结合律);
const _ = reuqire('lodash')
//三种写法
const f = _flowRight(_.toUpper, _.first, _.reverse);
const f = _.flowRight(_.toUpper, _.flowRight(_.first, _.reverse))
const f = _.flowRight(_.flowRight(_.toUpper, _.first), _.reverse)
console.log(f(['one', 'two', 'three']))//THREE
6、函数组合调试
const _ = reuqire('lodash')
const trace = _.curry((tab, v) => {
console.log(tag, v)
return v
})
//NEVER SAY DIE => never-say-die
const split = _.curry((sep, str) => _.split(str, sep))
const join = _.curry((sep, array) => _.join(array, sep))
const map = _.curry((fn, array) => _.map(array, fn))
const f = _.flowRight(join('-'), trace('map 之后'), map(_.toLower), trace('split 之后'), split(' '))
console.log(f('NEVER SAY DIE'))
7、Lodash的fp模块
//lodash 的 fp 模块
const fp = reuqire('lodash/fp')
const f = fp.flowRight(fp.join('-'), fp.map(fp.toLower), fp.split(' '))
console.log(f('NEVER SAY DIE'))
//lodash 和 lodash/fp 模块中 map 方法的区别
const fp = reuqire('lodash')
console.log(_.map(['23', '8', '10']), paeseInt) //[23, NAN, 2] paeseInt接收三个参数(‘元素’,‘索引‘,’数组‘)
parseInt('23', 0, array) //23
parseInt('8', 0, array) //NAN
parseInt('10', 0, array) //2
const fp = reuqire('lodash/fp')
console.log(fp.map(parseInt, ['23', '8', '10'])) //[23, 8, 10]
8、PointFree
我们可以把数据处理的过程定义成与数据无关的合成运算,不需要用到代表数据的那个参 数,只要把简单的运算步骤合成到一起,在使用这种模式之前我们需要定义一些辅助的基本运算函数。
- 不需要指明处理的数据
- 只需要合成运算过程
- 需要定义一些辅助的基本运算函数
//pointFree
//Hello world => hello_world
const fp = reuqire('lodash')
const f = fp.flowRight(fp.replace(/\s+/g, '_', fp.toLower))
console.log(f('Hello world')) //hello_world