Skip to content

函数缓存怎么做? ​

同一组输入会反复得到同一个结果时,把结果存下来,下次直接返回。缓存键必须覆盖全部会影响结果的输入,并且要有上限或失效条件。

原理 ​

js
function memoize(fn) {
  const cache = new Map()
  return function (...args) {
    const key = JSON.stringify(args)
    if (cache.has(key)) return cache.get(key)
    const value = fn.apply(this, args)
    cache.set(key, value)
    return value
  }
}

JSON.stringify 不能区分键顺序不同的对象,也处理不了函数、循环引用。参数是原始值时,用它们拼一个字符串更稳。对象参数要先规定规范化方式。

Vue 的 computed、React 的 useMemo 是「依赖变了才重算」。它们缓存的是一次渲染里的派生值,不是无限增长的 Map。见 运行时优化。

追问 ​

什么时候不该缓存?

结果依赖时间、随机数或还没结束的请求。计算本身很便宜,查缓存的成本更高。缓存会把大对象留在内存里,组件卸载时要能丢掉这份 Map。

和防抖的差别?

防抖减少调用次数。缓存允许调用,但重复输入不再计算。搜索框通常两者都要:停下来再请求,相同关键字命中缓存。

易错点 ​

  • 缓存了带副作用的函数,第二次不执行副作用,界面不更新。
  • 没有容量上限,键空间无限时 Map 一直涨。
  • 参数是对象却用默认的引用相等,每次新对象都命不中。

相关 ​