缓存函数起到什么/多大的作用?

看到Vue源码中有一段这样的cached函数

/**
 * Create a cached version of a pure function.
 */
function cached (fn) {
  var cache = Object.create(null);
  return (function cachedFn (str) {
    var hit = cache[str];
    return hit || (cache[str] = fn(str))
  })
}

/**
 * Capitalize a string.
 */
var capitalize = cached(function (str) {
  return str.charAt(0).toUpperCase() + str.slice(1)
});

...

capitalize(camelizedId)

请问cached函数在这里起到什么样的缓存作用?意义大么?请大佬指教一下!

阅读 3.7k
1 个回答

函数式的思想,这里用到了 高阶函数(hof) 和 柯理化,以及 js 的闭包。

cached 函数是一个标准的 hof,接收一个函数,返回一个函数。不过它还做了一个小小的优化,就是利用闭包,在当前的函数作用域定义了一个空对象,返回的函数由于函数作用域链的存在,是可以访问这个 cache 对象的,另外参数 fn 同理可访问。

柯理化体现在,如果这个函数是

function cached(fn, str) {
  return fn(str);
}
function upper(str) {
  return str.charAt(0).toUpperCase() + str.slice(1)
}
cached(upper, camelizedId)

这样的,其实是一样可以解决问题的。只不过我每次调用的时候,都要传入两个参数,fn 和 str。柯理化把参数变成每次只传一个,第一个参数可以被闭包缓存,然后你以后每次调用默认就有了第一个参数。比如这里返回了一个新的函数 capitalize,你每次只需要传入 str 就可以了,函数调用的时候比较简洁。另外,类似形式的都可以使用,比如你有一个把末尾字符小写的函数 (str) => str.slice(0, str.length - 2) + str.charAt(str.length - 1).toLowerCase(),当然这种情况很少。。。这个处理也是很麻烦的。所以如果你把这个小写函数做同样的 cached 处理,会得到一个新的函数。

其实作者最想用的还是 cache 对象,因为你会发现上面我的操作,完全是做无用功,传入一个函数,一个
str,执行 fn(str),感觉多此一举,但其实多了一个作用域可以缓存。作用是把处理过的 str 缓存到对象里,以后再传入同样的,就直接从对象里取,不用再调用 fn 了。

说意义的话,就是细节的优化吧,看起来处理的更优雅。性能提升的话,如果是大量的使用这个函数,直接取缓存的意义重大。如果调用不多,多执行几次,现在 js 的性能还是没啥问题的。

安利fp-code

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题