0%

函数组合

函数组合

这就是组合(compose)

1
2
3
4
5
var compose = function(f,g) {
return function(x) {
return f(g(x));
};
};

fg 都是函数,x是在他们之间通过”管道”传输的值

组合看起来像是在饲养函数。你就是饲养员,选择两个有特点又遭你喜欢的函数,让它们结合,产下一个崭新的函数。组合的用法如下:

1
2
3
4
5
6
var toUpperCase = function(x) { return x.toUpperCase(); };
var exclaim = function(x) { return x + '!'; };

var shout = compose(exclaim, toUpperCase);

shout("send in the clowns");

应用compose函数

假定有这样一个需求:对一个给定的数字四舍五入求值,数字为字符型。

常规实现:

1
2
3
let n = '3.56'
let data = parseFloat(n)
let result = Math.round(data) // => 4 最终结果

用compose函数改写:

1
2
3
let n = '3.56'
let number = compose(Math.round,parseFloat)
let result = number(n); // =>4 最终结果

函数组合应用

考虑一个小功能:将数组最后一个元素大写,假设 log head reverse toUpperCase 函数存在

命令式的写法:

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

面向对象的写法:

1
2
3
4
arr.reverse()
.head()
.toUpperCase()
.log()

链式调用看起来顺眼多了,然而问题在于,原型链上可供我们链式调用的函数是有限的,而需求是无限的 ,这限制了我们的逻辑表现力。

现在通过组合,我们如何实现之前的功能:

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

通过参数我们可以很清晰的看出发生了 uppderLastItem 做了什么,它完成了一套流水线,所有经过这条流水线的参数都会经历:reverse -> head -> toUpperCase -> log 这些函数的加工,最后生成结果。

函数组合的好处

函数组合的好处显而易见,它让代码变得简单而富有可读性,同时通过不同的组合方式,我们可以轻易组合出其他常用函数,让我们的代码更具表现力

1
2
3
4
5
6
7
// 组合方式 1
const last = compose(head, reverse);
const shout = compose(log, toUpperCase);
const shoutLast = compose(shout, last);
// 组合方式 2
const lastUppder = compose(toUpperCase, head, reverse);
const logLastUpper = compose(log, lastUppder);