JavaScript是如何实现函数缓存的呢?

129 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第N天,点击查看活动详情

什么是函数缓存

函数缓存,就是将函数运算过的结果进行缓存,本质上就是用空间(缓存存储)换时间(计算过程),一般用于缓存数据计算结果和缓存对象

实现函数缓存

实现函数缓存我们主要使用到的有闭包、柯里化、高阶函数

闭包

闭包可以简单理解成内部的函数可以访问外部函数的变量

(function () {
  const obj = {
    name: '小王'
  }
  function fn1 () {
    console.log(obj.name) // 小王
  }
  fn1()
  })()

(function(){})()这种写法是函数的自调用,我们在fn1里可以访问到fn里的变量,这就是闭包,实现了函数缓存

函数柯里化

把接受多个参数的函数转换成接受一个单一参数的函数

const fn3 = (a, b) => {
  return a + b
}
console.log(fn3(1, 2)) // 3
// 函数柯里化
const fn4 = a => {
  return function (b) {
    return a + b
    }
  }
console.log(fn4(1)(2)) // 3

将一个二元函数拆分成两个一元函数 高阶函数

通过接收其他函数作为参数或返回其他函数的函数

function First () {
  let a = 99
  function Second () {
    return (a = 88)
  }
   return Second
}
const num = First()
console.log(num()) // 88

函数 First 返回另一个函数 Secondnum 现在持有对 First 中定义的Second 函数的引用。由于闭包特性,a的值能够被修改和得到

举个例子使用闭包和柯里化配合实现函数缓存

const memoize = function (func, content) {
let cache = Object.create(null)
content = content || this
return (...key) => {
if (!cache[key]) {
  cache[key] = func.apply(content, key)
}
return cache[key]
}
}

调用方式

const calc = memoize(fn3);
const num1 = calc(100,200)
const num2 = calc(100,200) // 缓存得到的结果
  • 在当前函数作用域定义了一个空对象,用于缓存运行结果
  • 运用柯里化返回一个函数,返回的函数由于闭包特性,可以访问到cache
  • 然后判断输入参数是不是在cache的中。如果已经存在,直接返回cache的内容,如果没有存在,使用函数func对输入参数求值,然后把结果存储在cache

三、函数缓存应用场景

虽然使用缓存效率是非常高的,但并不是所有场景都适用,以下几种情况下,适合使用缓存:

  • 对于昂贵的函数调用,执行复杂计算的函数
  • 对于具有有限且高度重复输入范围的函数
  • 对于具有重复输入值的递归函数
  • 对于纯函数,即每次使用特定输入调用时返回相同输出的函数