如何在javascript中实现下划线memoize

时间:2014-06-30 09:25:38

标签: javascript underscore.js memoization

我正在开发自己的函数式编程库,现在引用underscore

memoize _.memoize(function, [hashFunction])

  

通过缓存计算结果来记忆给定函数。对于加速慢速运行计算很有用。如果传递了一个可选的hashFunction,它将用于根据原始函数的参数计算用于存储结果的哈希键。默认的hashFunction只使用memoized函数的第一个参数作为键。

var fibonacci = _.memoize(function(n) {
  return n < 2 ? n: fibonacci(n - 1) + fibonacci(n - 2);
});

以上代码能够自动记忆而不处理array看起来有点神奇,我看到了下面的源代码,但内部设计仍然不清楚。

 // Memoize an expensive function by storing its results.
  _.memoize = function(func, hasher) {
    var memoize = function(key) {
      var cache = memoize.cache;
      var address = hasher ? hasher.apply(this, arguments) : key;
      if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
      return cache[key];
    };
    memoize.cache = {};
    return memoize;
  };

有人能简单介绍一下发生了什么吗?

赞赏。

1 个答案:

答案 0 :(得分:7)

memoizecachememoize.cache = {}),用于存储函数调用的结果。当它被调用时,它确定address以两种方式存储结果:调用hasher函数或key参数。

hasher函数的工作原理如下(来自下划线页面):

  

如果传递了一个可选的hashFunction,它将用于计算   用于存储结果的哈希键,基于参数   原始功能。默认的hashFunction只使用第一个   将记忆函数作为关键参数。

然后,它调用您传递的函数func.apply(...),并将结果存储在cache[address]

第二次调用memoized函数时,结果已经在缓存中(!_.has(..)将返回false)并且不会重复计算。

我不明白为什么它返回cache[key]而不是cache[address]很难...在我看来cache[address]将是正确的选择。

更新

正如评论中所指出的,您提供的代码不是memoize的最新实现。这是最新的实现(1.6.0):

_.memoize = function(func, hasher) {
    var memo = {};
    hasher || (hasher = _.identity);
    return function() {
      var key = hasher.apply(this, arguments);
      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
    };
  }; 

它的工作方式相同,只是它更优雅;如果没有提供hasher函数,则它使用_.identity作为键,这是一个只返回作为参数传递的值的函数:

_.identity = function(value) { return value; }

除此之外,cache现在称为memo,但工作方式相同。