pocket-lodash icon indicating copy to clipboard operation
pocket-lodash copied to clipboard

lodash源码分析之memoize

Open HeftyKoo opened this issue 4 years ago • 2 comments

本文为读 lodash 源码的第六十六篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash

gitbook也会同步仓库的更新,gitbook地址:pocket-lodash

源码分析

memoize 的作用是缓存传入函数的计算结果,这个对于重复执行计算量繁重的函数相当有用。

源码如下:

function memoize(func, resolver) {
  if (typeof func !== 'function' || (resolver != null && typeof resolver !== 'function')) {
    throw new TypeError('Expected a function')
  }
  const memoized = function(...args) {
    const key = resolver ? resolver.apply(this, args) : args[0]
    const cache = memoized.cache

    if (cache.has(key)) {
      return cache.get(key)
    }
    const result = func.apply(this, args)
    memoized.cache = cache.set(key, result) || cache
    return result
  }
  memoized.cache = new (memoize.Cache || Map)
  return memoized
}

memoize.Cache = Map

可以看到,memoize 接收两个参数,第一个参数 func 即为要执行计算的函数,可选参数 resolver 可以返回一个值作为缓存结果的 key

memoize 最终返回的结果也一个函数 memoized,在使用原函数 func 的地方,替换成这个返回函数的调用,就会获得结果缓存的能力。

参数合规性检测

if (typeof func !== 'function' || (resolver != null && typeof resolver !== 'function')) {
  throw new TypeError('Expected a function')
}

这段是检测传入的 func 必须为函数,如果 resolve 也有传,也必须要传入函数。

获取缓存的 key

const key = resolver ? resolver.apply(this, args) : args[0]

如果有传 resolver 函数,则会将所有参数都传给 resolver 函数,由 resolver 函数根据参数来计算出缓存的 key

如果没有传 resolver 函数,则默认取第一个参数作为缓存的 key

设置缓存

const cache = memoized.cache
const result = func.apply(this, args)
memoized.cache = cache.set(key, result) || cache

memoize.Cache = Map

可以看到,缓存直接存储在 memoizedcache 字段中,并且默认使用 Map 来存储。

使用者也可以使用其他的缓存方式,直接将构造函数赋值给 memoize.Cache 即可,但是必须具备和 Map 一样的方法。

在函数第一次调用,或者在参数改动,造成缓存的 key 第一次出现的时候,肯定是没有缓存的,这时 memoized 会调用原函数 func 得到计算结果,并且将计算结果存储起来。

使用缓存

if (cache.has(key)) {
  return cache.get(key)
}

缓存的使用其实就是判断缓存池里有没有,如果有,就直接返回结果,不再执行原函数。

License

署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)

最后,所有文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见:

作者:对角另一面

HeftyKoo avatar Feb 01 '20 15:02 HeftyKoo

源码分析后的第一个memoize拼写错误,目前为mamoize :grimacing:

KK-AI-LL avatar May 26 '21 14:05 KK-AI-LL

源码分析后的第一个memoize拼写错误,目前为mamoize 😬

谢谢指正

HeftyKoo avatar May 27 '21 02:05 HeftyKoo