缓存函数
例子
比如Vue的computed就使用了缓存的方式
实现
使用闭包(和柯里化),每次调用函数都判断缓存对象内是否存有结果,如果已经存在即直接使用cache[args.toString()],否则就将函数的返回值存入缓存
// 缓存函数
function cachedFun(fun) {
let cache = Object.create(null)
// 实际应用了柯里化/偏函数
return function (...args) {
// 在js中, 连续的赋值不会返回bool, 而是返回赋的值
return cache[args.toString()] || (cache[args.toString()] = fun(...args))
}
}
function sum(...args) {
// console.log(args.reduce((r, a) => r + a))
console.log('此时调用了函数, 没有使用缓存结果')
return args.reduce((r, a) => r + a)
}
let cachedSum = cachedFun(sum)
console.log(cachedSum(1, 2, 456))
// 第二次没有走函数,没有打印文字
console.log(cachedSum(1, 2, 456))
柯里化
定义
将需传入多个参数的函数转化为每次传入一个参数的多个嵌套的函数(闭包)。
实现方式
不断的return函数(闭包),而内层的函数可以访问外层函数的所有属性
意义
- 未柯里化,正常传参
// 柯里化
let obj = {
fqm: 'fqmyysjjd'
}
// 假设从别的文件导入的
let fqm = obj.fqm
// 假设在本文件内的
let myObj = {
// ...
yy: function (addition, ...args) {
// 对于现有的结果做一些处理
return cachedSum(...args) + ': ' + addition
}
}
function foo(addition, fun, ...args) {
return fun(addition, ...args)
}
console.log(foo(fqm, myObj.yy, 1, 2, 456))
参数混在一起,很混乱,且不好封装
- 使用柯里化后
// 使用柯里化, 即参数拆分
function curryFoo(addition) {
return fun => {
return (...args) => fun(addition, ...args)
}
}
console.log( curryFoo(fqm)(myObj.yy)(1, 2, 456) )
let newFoo = curryFoo(fqm)(myObj.yy)
// 可以封装,更好使用,且暴露的newFoo方法无法直接更改
console.log(newFoo(1, 2, 3))
console.log(newFoo(1, 2, 5))
此时,使用起来,逻辑更为清晰,且可以更自由的封装
偏函数
实现
即把参数分解为两部分,而不像柯里化严格每次只return一个函数传入一个参数,分解n份,可以理解为柯里化的一种特殊情况
// 偏函数: 柯里化的一种特定的使用方式
// 传入特殊处理的结果和函数
function partialFoo(addition, fun) {
return function (...args) {
return fun(addition, ...args)
}
}
let newSum = partialFoo(fqm, myObj.yy)
console.log(newSum(1, 2, 455))
如有差错且您有时间,请帮忙指正,不胜感谢