返回列表

函数结果缓存优化

默认分类 2018/11/15 09:44

最近两天在读vue源码时,看到cached方法,如下:

/**
 * Create a cached version of a pure function.
 */
export function cached<F: Function> (fn: F): F {
  const cache = Object.create(null)
  return (function cachedFn (str: string) {
    const hit = cache[str]
    return hit || (cache[str] = fn(str))
  }: any)
}

/**
* 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))
  })
}

一开始没太看明白把函数包装一次有什么用处,网上找了下资料, https://segmentfault.com/q/1010000013629607/a-1020000013629988 这里有提到 cached会把fn的执行结果缓存起来,下次直接返回。看到这里这个函数做什么的基本 就了然了。然后顺手写了个小示例,结果发现个小问题。

代码如下:

function cached(fn) {
  var cache = Object.create(null)
  return (function cachedFn(str) {
    var hit = cache[str]
    return hit !== undefined ? hit : (cache[str] = fn(str))
  })
}
function findPrime(num) {
  num = BigInt(num)
  var result = true
  for (var i = 2n; i < num; i++) {
    if (num % i === 0n) {
      result = false
    }
  }
  return result
}
var isPrime1 = function (nn) {
  var t1 = new Date()
  var result = findPrime(nn)
  var t2 = new Date()
  console.log('Use time: ', t2.getTime() - t1.getTime())
  return result
}
var findPrime2 = cached(findPrime)
var isPrime2 = function (nn) {
  var t1 = new Date()
  var result = findPrime2(nn)
  var t2 = new Date()
  console.log('Use time: ', t2.getTime() - t1.getTime())
  return result
}
isPrime1(8271212n)
>> Use time:  1516
>> false
isPrime1(8271212n)
>> Use time:  1503
>> false
//////////////////////////////
isPrime2(8271212n)
>> Use time:  1503
>> false
isPrime2(8271212n)
>> Use time:  0
>> false

原代码中的 return hit || (cache[str] = fn(str)) 在fn返回值是布尔值或者数字时, 运算结果有可能不会被缓存,比如返回 false 或 0 时,遂做了一点小修改 return hit !== undefined ? hit : (cache[str] = fn(str)) 以兼容上面的情况。