目录
纯函数
对于相同的输入函数,始终得到相同的输出。
可缓存
因为存函数对相同的输入始终有相同的输出,所以可以把纯函数的的结果缓存起来。
loadsh中memoize缓存函数简单实现
function memoize(f){
let cache = {}
return function () {
let arg_str = JSON.stringify(arguments);
cache[arg_str] = cache[arg_str] || f.apply(f, arguments);
return cache[arg_str];
}
}
function getSum(a, b){
console.log('执行了')
return a + b;
}
const cacheSum = memoize(getSum);
cacheSum(1,2);
cacheSum(1,2);
副作用
如果函数依赖外部的状态就无法保证输出相同,就会带来副作用(让一个函数变为不纯)。
示例
例如下面当mini改变时就会给checkAge带来副作用(相同的输入,输出不同)。
let mini = 18;
function checkAge(age) {
return age >= mini
}
副作用一般来源于:
- 配置文件
- 数据库
- 获取用户的输入
- ...
接口的幂等性
接口可重复调用,在调用方多次调用的情况下,接口最终得到的结果是一致的。
函数的柯里化
当一个函数有多个参数的时候先传递一部分参数调用它(这部分参数以后永远不变),然后返回一个新的函数接收剩下的参数,返回结果。
function checkAge(min, age) {
return age >= min;
}
// 柯里化后
function checkAge(min) {
return function(age) {
return age >= min;
}
}
lodsh中的curry方法简单实现
function curry(func) {
return function curriedFn(...args) {
if(args.length < func.length) {
return function() {
// 注意arguments参数是类数组需要通过Array.from转化为数组
return curriedFn(...args.concat(Array.from(arguments)))
}
}
return func(...args)
}
}
function getSum(a, b, c){
return a + b + c;
}
const curried = curry(getSum);
curried(1, 2, 3);
const sumBC = curried(1)
sumBC(2, 3);
lodash中的fp模块
其中map、split等函数都用了函数柯里化。当只传入一个参数时,返回的是一个函数。
const fP = require('lodash/fp');
fp.map(fp.toUpper,['a', 'b', 'c']);
const toUpper = fp.map(fp.toUpper);
toUpper(['a', 'b', 'c']);
fp.split(' ', 'hello world');
const split = fp.split(' ');
split('hello world');
函数的组合
如果一个函数要经过多个函数处理才能得到最终值,这个时候可以把中间过程的函数和并成一个函数(g(f(x)) => h(g,f))。
lodash中的flowRight方法简单实现
function flowRight(...args) {
return function(value) {
return args.reverse().reduce(function(acc, fn) {
return fn(acc)
}, value)
}
}
const reverse = arr => arr.reverse()
const first = arr => arr[0]
const f = flowRight(first, reverse)
f([1, 2, 3])
数组reduce方法介绍
JavaScript中常用函数方法(数组篇)_YF-SOD的博客-CSDN博客_javascript数组函数
函子Functor
一个特殊的容器,通过一个普通的对象来实现,该对象具有map方法,map方法可以运行一个函数对值进行处理(变形关系)。
容器:包含值和值的变形关系,这个变形关系就是函数。
class Container {
static of (value) {
return new Container(value)
}
constructor (value) {
this._value = value
}
map (fn) {
return this._value ? Container.of(fun(this._value)) : Container.of(null)
}
}
let r = Container.of(4).map(x => x * x)
IO函子
IO函子中的_value是一个函数,这里把函数作为值来处理。
IO函子可以把不纯的动作存储在_value中,延迟执行这个不纯的操作,把不操作交给调用者处理。
const fp = require('lodash/fp')
class IO {
static of (x) {
return new IO(function () {
return x;
})
}
constructor (fn) {
this._value = fn
}
map(fn) {
return new IO(fp.flowRight(fn, this._value))
}
}
let r = IO.of(process).map(p => p.execPath)
r._value()// 返回该文件路径