一、纯函数
特点:
- 对于相同的输入,永远会得到相同的输出。
- 没有任何可观察的副作用
- 不依赖外部环境的状态
例子:
//Array.slice是纯函数,Array.splice不是纯函数,存在副作用
var arr = [1,2,3,4,5];
arr.slice(0,3);
arr.splice(0,3);
优点:
- 降低系统复杂性
- 可缓存
var min = 18;
//checkAge不是纯函数,因为其依赖外部变量min。
var checkAge1 = age=> age>min;
//虽然checkAge2是纯函数,但缺乏扩展性
var checkAge2 = age=>age>18;
二、函数柯理化
特点:传递函数的一部分参数来调用,返回一个函数去处理剩下的参数。
例子一:改写刚才的checkAge函数,使其具备可扩展性
var checkAge = min=>(age=>age>min);
//通过传入参数18,将min变量固定下来,提高扩展性。
var checkAge18 = checkAge(18);
//纯函数,刚刚的!
checkAge18(20); //true;
例子二:函数柯理化过程
//柯理化之前
function add(x,y){
return x+y;
}
//柯理化之后
function addX(y){
return function(x){
return x+y;
}
}
addX(2)(1); //3
例子三:通过函数柯理化来“缓存”参数
function test(p1,p2){
this.val = p1+p2;
}
var bar = test.bind(null,"p1");
var baz = new bar("p2");
console.log(baz.val); //p1p2
优点:
- “预加载”函数的方法
- 避免纯函数的硬编码,提高可扩展性
- 降低纯函数对外部变量的依赖
三、函数组合
特点:有效解决函数嵌套的问题h(g(f(x)))
const compose = (f,g)=>( x=>f(g(x)));
var first = arr=>arr[0];
var reverse = arr=>arr.reverse();
var last = compose(first,reverse);
last([0,1,2,3,4,5]); //5
四、Point Free
把对象自带的方法转换成纯函数,不要命名中间转瞬即逝的变量。
Bad Case:
const f = str=>str.toUpperCase().split(' ');
Good Case:
const compose = (f,g)=>( x=>f(g(x)));
var toUpperCase = word=> word.toUpperCase();
var split = x=>(str=>str.split(x));
var f = compose(split(' '), toUpperCase);
f('abcd efgh'); //['ABCD','EFGH']
优点:减少不必要的命名,让代码保持简洁、通用
五、声明式与命令式代码
//命令式
var CEOs = [];
for( var i=0; i<companies.length; ++i ){
CEOs.push(compaines[i].CEO);
}
//声明式
let CEOs = companies.map(c=>c.CEO);
优点:
- 专注于编写业务代码,不需要考虑内部实现。
- 优化代码时,只需要集中目光在函数内部即可。
六、惰性求值