函数式编程

纯函数

1
2
3
function add (x, y) {
return x + y;
}

大多数的纯函数都应该有至少一个参数。

所有的纯函数都应该返回一些东西。

纯函数对于给定的输入,总是产生相同的输出。

纯函数没有函数副作用。

纯函数有可缓存性。

我的理解:纯函数不依赖任何出了传入参数给定的东西。比如外部变量,获取个系统时间之类的,因为输入相同,输出一定要相同。

不可变性

在函数式编程中没有变量。也就是说即使传入的参数,到了执行的时候也不能被改变。里面任何时候定义的变量也都不能改,被声明时赋值了什么就是什么。

函数式编程通过拷贝处理但只修改。🤔

没有循环,不能用for之类的,用递归。递归不会修改旧值,但是使用了旧值的计算结果。

1
2
3
4
5
6
7
function sumRange (start, end, acc) {
if (start > end) {
return acc;
}
return sumRange(start + 1, end, acc + start);
}
console.log(sumRange(1, 10, 0)) // 55

这里函数内部并没有改变参数的值,但是在递归调用的时候可能会对参数值进行重新赋值,这就是使用了旧值的计算结果,但是那是另一个函数了。

不可变性的好处:不可变性创建了更简单安全的代码。🤔

函数柯里化

定义:传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。

1
2
3
4
5
6
7
8
9
function add (x) {
return function (y) {
return x + y;
}
}
add(1)(2); // 3

var add10 = add(10);
add10(20); // 30

函数组合

函数组合就是传入几个参数,然后在定义函数组合的函数中执行这几个参数,或者在return的函数中执行这几个参数。

1
2
3
4
5
6
var compose = (f, g) => (x => f(g(x)));

var foo = x => x + 1;
var bar = x => x * 5;

compose(foo, bar)(2); // 11

Point Free

声明式与命令式代码

命令式代码就是每一步都是指定去做。

1
2
3
4
var CEOs = [];
for (var i = 0, len = companies.length; i < len; i ++) {
CEOs.push(companies[i].CEO);
}

声明式代码是通过写表达式的方式来声明我们想干什么。声明的是做什么。

1
var CEOs = companies.map(c => c.CEO);

容器、Functor

容器就是讲给定的值包裹起来,可能还有其他的一些作用。比如说衣服将人包裹起来,还有保暖,遮体的作用,脱掉了衣服人还是人。

例子能看明白怎么实现,但是不是很理解:

1
2
3
4
5
6
7
8
9
var Container = function (x) {
this.__value = x;
}
Container.of = x => new Container(x);
Container.prototype.map = f => Container.of(f(this.__value));

Container.of(3)
.map(x => x + 1) // Container(4)
.map(x => 'Result is ' + x); // Container('Result is 4')

执行的时候感觉有问题,每次调用 Container.of 的时候,都是返回一个新的Container对象,这几个对象不是一个。也就是说上面的链式调用每个都是一个新的 Container ,而map中用到的 this.__value 就是 undefined 了。