JS实现函数缓存

385 阅读1分钟

原理

  • 闭包
  • 柯里化
  • 高阶函数

例子:求和

正常的循环累加代码

 function add() {
   let sum = 0
   for (let i = 0; i < arguments.length; i++) {
     sum += arguments[i]
   }
   return sum
 }

使用数组的reduce方法

 function add() {
   var arr = Array.prototype.slice.call(arguments)
   return arr.reduce(function (prev, cur) {
     return prev + cur;
   }, 0);
 }

但多次传入同样的参数 如 add(1, 2, 3) 都将执行运算对应的次数,将会耗费一定的性能。

使用函数缓存

使用闭包,将每次运算的参数与结果存入置cache对象中,如果cache中有,便直接获取,来达到缓存的目的

 let add = (function () {
   let cache = {}
 ​
   return function () {
     let args = Array.prototype.join.call(arguments, ',')
     if (cache[args]) {
       return cache[args]
     }
     let sum = 0
     for (let i = 0; i < arguments.length; i++) {
       sum += arguments[i]
     }
     return cache[args] = sum
   }
 })()
 ​
 add(1, 2, 3) // 输出6
 add(1, 2, 3) // 直接从cache中获取

已经达到缓存的目的了,但这时我想将乘法也想实现缓存的目的,那么又得写一大行这样的代码,同时原本求和的代码又想单独分离出来,就可以使用代理模式,具体演示如下

代理模式

创建缓存代理的工厂

 let memoize = function (fn) {
   let cache = {}
   return function () {
     let args = Array.prototype.join.call(arguments, ',')
     if (args in cache) {
       return cache[args]
     }
     return cache[args] = fn.apply(this.arguments)
   }
 }

那么通过memoize 就能将函数运行后的结果给缓存起来,如

 let add1 = memoize(add)
 ​
 add1(1, 2, 3) // 输出6
 add1(1, 2, 3) // 直接从cache中获取

我们只需要编写我们正常的业务逻辑(加法,乘法等),然后通过memoize调用 便可达到缓存的目的

同理乘法

 function mult() {
   let a = 0
   for (let i = 0; i < arguments.length; i++) {
     a *= arguments[i]
   }
   return a
 }
 ​
 let mult1 = memoize(mult)
 ​
 mult1(1, 2, 3) // 输出6
 mult1(1, 2, 3) // 直接从cache中获取