概念
函数式编程是一种编程范式,主要是利用函数把运算过程封装起来,通过组合各种函数来处理数据,通过串联多个函数来计算,类似一条流水线。
特点
函数是一等公民
函数与其他数据类型一样,处于平等地位,可以赋值给变量,可以作为函数入参或者返回值。
ajaxCall(json => callback(json)); // 脱裤子放P
// 等价于这行
ajaxCall(callback);
高阶函数: 把函数作为参数或者返回值的一类函数。
声明式编程
声明式编程关心做什么,命令式编程关心怎么做
// 命令式
var makes = [];
for (i = 0; i < cars.length; i++) {
makes.push(cars[i].make);
}
// 声明式
var makes = cars.map(function(car){ return car.make; });
纯函数
- 无状态:函数的输出仅取决于输入,而不依赖外部状态;
- 无副作用: 不修改外部状态,不修改入参。
意味着相同的输入,永远会得到相同的输出。
var xs = [1,2,3,4,5];
// 纯的
xs.slice(0,3);
//=> [1,2,3]
// 不纯的
xs.splice(0,3); //改变原数组
//=> [1,2,3]
其他优点:
- 可缓存性,因为相同的输入得会得到相同的输出,那么可以缓存函数的结果。
- 可移植性/自文档化,纯函数的依赖很明确,因此更易于观察和理解
- 可测试性,函数让测试更加简单,只需简单地给函数一个输入,然后断言输出就可以了。
- 引用透明性,如果一段代码可以替换成它执行所得的结果,而且是在不改变整个程序行为的前提下替换的,那么我们就说这段代码是引用透明的。
柯里化(curry)
柯里化的意思是将一个多元函数,转换成一个依次调用的单元函数。
柯里化函数会接收一些参数,然后不会立即求值,而是继续返回一个新函数,将传入的参数通过闭包的形式保存,等到被真正求值的时候,,再进行求值。 ```javascript var add = function(x) { return function(y) { return x + y; }; }; const increment = add(1);f(a,b,c) → f(a)(b)(c)
increment(10); // 11
<a name="cxOSF"></a>
### 偏函数
> **偏函数** ( Partial )是指固定一个函数的一些参数,然后产生另一个更小元的函数。
> In computer science, partial application(or partial function application) refers to the process of fixing a number of arguments to a function, producing another function of smaller arity.
- 柯里化:将多参数函数转换成多个单参数函数,也就是将一个 n 元函数转换成 n 个一元函数
- 偏函数:则是固定一个函数的一个或多个参数,也就是将一个 n 元函数转换成一个 n - x 元函数
```javascript
// 柯里化
f(a,b,c) → f(a)(b)(c)
// 偏函数
f(a,b,c) → f(a)(b,c) / f(a,b)(c)
组合(compose)
函数组合的目的是将多个函数组合成一个函数
const compose = (f, g) => x => f(g(x))
const f = x => x + 1;
const g = x => x * 2;
const fg = compose(f, g);
fg(1) //3
function compose(...fns) {
return fns.reduce((a,b) => {
return (...args) => {
return a(b(...args))
}
})
}
function fn1(a) {
console.log('fn1: ', a);
return a+1
}
function fn2(a) {
console.log('fn2: ', a);
return a+1
}
function fn3(a) {
console.log('fn3: ', a);
return a+1
}
console.log(compose(fn1, fn2, fn3)(1));
参考
简明 JavaScript 函数式编程——入门篇—网易云
浅析JavaScript函数式编程—转转
《函数式编程指北》中文翻译
https://juejin.cn/post/6844903909169823751