“函数式编程”是一种”编程范式”(programming paradigm),也就是如何编写程序的方法论。
特点
函数是”第一等公民”
所谓”第一等公民”(first class),指的是函数可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。
1 2 3 4 5 6
| var add = function add (a, b) { return a + b } function (a, b, add) { add(a, b) }
|
独立与外界
函数内部逻辑不依赖于外部变量,所有的依赖都通过参数传入(任何时候只要参数相同,函数的返回值总是相同的)。所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。
1 2 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)是执行某种操作,没有返回值。
函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。
1 2 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),以及模块化组合。
易于理解
函数式编程的自由度很高,可以写出很接近自然语言的代码。
1 2 3
| (1 + 2) * 3 - 4 subtract(multiply(add(1,2), 3), 4) add(1,2).multiply(3).subtract(4)
|
表现形式
函数柯里化
1 2 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)();
|
函数的组合
1 2 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)
|