导读
在写这篇文章之前,一直比较犹豫要不要写,一来是觉得函数式编程本身更多的是一种编程思想,怕表达的不够清楚,二来这块相对较难,平时又实践的少。但是在各类公众号包括掘金看到过很多关于函数式的文章,很强大,但是一知半解,所以我觉得很有必要从underscore为切入点,来理解和运用函数式编程,希望大家能和我一起把函数式应用于我们的日常编码之中,使我们的代码拓展性和灵活性大大增强。
概述
"函数式编程"是一种"编程范式"(programming paradigm),是一种优秀的编程思想。"函数式编程"就是将一系列声明式函数通过自由组合的方式构建出我们需要实现的功能,其中各个函数的功能职责单一,相互解耦。对于需求将各个函数进行按需组合即可,当新的需求来的时候,只需要重新添加函数或者再自由组合。所以函数式编程是“组合优于继承”,“声明式”,“高内聚,低耦合”,“高拓展性和灵活性”思想的具体体现。本文不想引起FP和OOP的争议,旨在让读者能够理解和运用FP进行开发。
在一开始,我先使用mqyqingfeng大大举的一个例子来解释函数式编程:
需求
我们需要写一个函数,输入 'kevin',返回 'HELLO, KEVIN'。
一般实现
var greet = function(x){
return 'HELLO,'+x.toUpperCase();
}
根据之前的概念,使用函数式编程
var toUpperCase = function(x) { return x.toUpperCase(); };
var hello = function(x) { return 'HELLO, ' + x; };
var greet = function(x){
return hello(toUpperCase(x));
};
greet('kevin');
此处greet就是将hello和toUpperCase进行组合得到,hello和toUpperCase是纯函数,此时输入kevin,输出HELLO, KEVIN。

如图,我们把greet看成一个黑盒,hello,toUpperCase,...是声明式函数,通过连接线将它们自由组合,组成greet1,greet2,...,用于只需要关注greet的功能,输入和输出即可
在此处必须指明的是hello和toUpperCase必须是纯函数,保证这个黑盒,在输入相同数据的情况下,输出一定相同。
var compose = function(f,g) {
return function(x) {
return f(g(x));
};
};
var greet = compose(hello, toUpperCase);
greet('kevin');
上述使用compose对函数f和g进行组合封装,使用x作为高阶函数compose(a,b,c,d...)的输入,执行compose函数返回需要的值。
实现
下面摘自underscore官网对于compose的解释和使用方式:

underscore官网对于compose的释义和使用方式通俗易懂
在概述中,我们hello,toUpperCase进行组合的实现如下
var greet = function(x){
return hello(toUpperCase(x));
};
在设计compose的实现时,上述显然是不合适的。首先compose返回function,其次形参是fn,我们先打个框框出来:
var compose = function() {
var args = arguments;
var start = args.length - 1;
return function() {
//获取传入compose的参数,并且从右往左,将结果迭代执行
};
};
进一步实现
_.compose = function() {
var args = arguments;
var start = args.length - 1;
return function() {
var i = start;
var result = args[start].apply(this, arguments);
while (i--) result = args[i].call(this, result);
return result;
};
};
Compose源码实现
上述正是underscore的源码实现。
注:对于compose中的形参fn,如果参数大于1,可以使用函数柯里化降维。
总结
本文写的比较简洁,篇幅少,旨在希望大家能够看完就懂,并且能够在实际开发中应用进去。特别是在React的开发中,redux,高阶组件也是compose思想的体现
参考文章
《函数式编程初探》
《函数式编程,真香》
《JavaScript函数式编程,真香之组合函数(二)》
《JavaScript专题之函数组合》
《JS 函数式编程指南》
《反对函数式编程的政治正确》