如何在javascript中实现下划线memoize

4 javascript memoization underscore.js

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

memoize _.memoize(function,[hashFunction])

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

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

上面的代码可以实现自动记忆而不需要处理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;
  };
Run Code Online (Sandbox Code Playgroud)

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

赞赏.

lin*_*ink 9

memoize有一个cache(memoize.cache = {})用于存储函数调用的结果.当它被调用时,它确定address通过两种方式存储结果:调用hasher函数或key参数.

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

如果传递了一个可选的hashFunction,它将用于根据原始函数的参数计算用于存储结果的哈希键.默认的hashFunction只使用memoized函数的第一个参数作为键.

然后,它调用您传递的函数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));
    };
  }; 
Run Code Online (Sandbox Code Playgroud)

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

_.identity = function(value) { return value; }
Run Code Online (Sandbox Code Playgroud)

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

  • 它使用_.identity根本不是很优雅。_.identity是一元的。 (2认同)