函数式编程
概念
把运算过程抽象
高阶函数 Higher order function
- 可以把函数作为参数传递给另一个函数
- 可以把函数作为另一个函数的返回值
闭包
一个解释是:
在一个作用域中可以访问调用另一个函数内部的函数
哪个是闭包?
function out() {
function inside() {
// do something
}
inside();
}
// or?
function out() {
return function inside() {
// do something
};
}
纯函数
相同的输入输出相同,没有任何可观察的副作用。
当函数依赖外部状态可能带来副作用,例如配置文件、数据库、获取用户的输入...
// 不纯 因为函数结果受外界变量 min 的影响
let min = 18;
function check(age) {
return age > min;
}
//纯函数
function check(age) {
let min = 18;
return age > min;
}
- 可缓存
- 可测试
- 并行处理?
柯里化
当一个函数有多个参数的时候,将这个函数改造为调用另一个只接收部分参数的函数,被调用的函数返回新的函数且被返回的函数可以继续接收最初参数中剩余的参数。
lodash
中有实现柯里化的函数 _.curry(func, [arity=func.length])
,返回新的柯里化(curry)函数。
手动实现
function curry(fn) {
return function inner(...args) {
// 拿到第一次调用传入的参数
if (args.length >= fn.length) {
// 如果传入的参数个数大于 fn 函数的形参个数则调用 fn
return fn.apply(this, args); // 直接调用最初传入的 fn 函数
}
return (...argsOther) => inner(...args, ...argsOther); // 否则返回一个可以接受剩余参数的函数 一直递归调用直到传入的参数个数满足 fn 形参个数
};
}
//测试
function add(a, b, c) {
return a + b + c;
}
const addCurried = curry(add);
console.log(addCurried(5, 2, 3)); // 10
console.log(addCurried(5, 2)(3)); // 10
console.log(addCurried(5)(2)(3)); // 10
函数组合
例如将数组最后一个元素转大写
function upper(arr) {
return arr.reverse()[0].toUpperCase(); // 这里会有几个连续调用的函数
}
将其组合后调用
const _ = require('lodash'); // 引入 lodash
const reverse = (arr) => _.reverse(arr); // 用于反转数组的函数
const first = (arr) => _.first(arr); // 获取数组的第一个元素
const upper = (ltr) => _.upperCase(ltr); // 将字符转大写
const lastToUpper = _.flowRight(upper, first, reverse); // 分别传入将要顺序执行的函数
console.log(lastToUpper(['tom', 'jam', 'alan'])); // 传入初始参数
// ALAN
简单实现 compose 函数
function compose(...args) {
return function (param) {
// 传入数据
return args.reverse().reduce((res, fn) => {
// 将初始传入的函数依次执行
return fn(res);
}, param);
};
}
// 测试下
const reverse = (arr) => _.reverse(arr);
const first = (arr) => _.first(arr);
const upper = (ltr) => _.upperCase(ltr);
const lastToUpper = compose(upper, first, reverse);
console.log(lastToUpper(['tom', 'jam', 'alan'])); // ALAN
详细参考: https://juejin.cn/post/6844903780329357320
Functor 函子
参考:
https://juejin.cn/post/6949523819400790053
https://juejin.cn/post/6844903762780225544