“函数式编程”是一种”编程范式”(programming paradigm),也就是如何编写程序的方法论。
特点
函数是”第一等公民”
所谓”第一等公民”(first class),指的是函数可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。
| 12
 3
 4
 5
 6
 
 | var add = function add (a, b) {return a + b
 }
 function (a, b, add) {
 add(a, b)
 }
 
 | 
独立与外界
函数内部逻辑不依赖于外部变量,所有的依赖都通过参数传入(任何时候只要参数相同,函数的返回值总是相同的)。所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | var a = 1, b = 2;
 function add (a, b) {
 return a + b
 }
 add (a, b)
 
 
 function add2 () {
 return a + b
 }
 add2()
 
 | 
只用”表达式”,不用”语句”
- “表达式”(expression)是一个单纯的运算过程,总是有返回值;
- “语句”(statement)是执行某种操作,没有返回值。
函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。
| 12
 3
 4
 5
 6
 7
 
 | var a = 1 + 2;
 var b = a * 3;
 var c = b - 4;
 
 
 var result = subtract(multiply(add(1,2), 3), 4);
 
 | 
意义
便于重用
由于对每一步运算都进行了封装,而且函数不依赖于外界,所以有很好的复用性。并且,每一个函数都可以被看做独立单元,很有利于进行单元测试(unit testing)和除错(debugging),以及模块化组合。
易于理解
函数式编程的自由度很高,可以写出很接近自然语言的代码。
| 12
 3
 
 | (1 + 2) * 3 - 4subtract(multiply(add(1,2), 3), 4)
 add(1,2).multiply(3).subtract(4)
 
 | 
表现形式
函数柯里化
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | var currying = function(fn) {
 var _args = [];
 return function _fn (...args) {
 if (args.length === 0) return fn.apply(this, _args);
 _args.push(...args);
 return _fn;
 };
 };
 var multi = (...args) => args.reduce((total, cur) => total + cur, 0);
 var sum = currying(multi);
 sum(100, 200)(300);
 sum(400);
 sum(3)(30)(300)();
 
 | 
函数的组合
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | function compose(...funcs) {
 if (funcs.length === 0) return a => a
 if (funcs.length === 1) return funcs[0]
 return funcs.reduce((a, b) => (...args) => a(b(...args)), a => a)
 }
 var fn1 = (i) => i * 2
 var fn2 = (i) => i + 2
 var fn3 = (i) => i % 2
 const func = compose(fn1,fn2,fn3)
 func(5)
 
 |