【问题标题】:Implementing Automatic Memoization (returns a closured function) in JavaScript在 JavaScript 中实现自动记忆(返回一个闭包函数)
【发布时间】:2014-08-20 18:00:04
【问题描述】:

我读过

http://www.sitepoint.com/implementing-memoization-in-javascript/

自动记忆

在前面的所有示例中,函数都经过显式修改以添加记忆功能。也可以在完全不修改功能的情况下实现记忆化基础设施。这很有用,因为它允许功能逻辑与记忆逻辑分开实现。这是通过创建一个实用函数来完成的,该函数将函数作为输入并对其应用记忆。以下 memoize() 函数将函数“func”作为输入。 memoize() 返回一个新函数,该函数将缓存机制包装在“func”周围。请注意,此函数不处理对象参数。为了处理对象,需要一个循环来单独检查每个参数并根据需要进行字符串化。

function memoize(func) {
  var memo = {};
  var slice = Array.prototype.slice;

  return function() {
    var args = slice.call(arguments);

    if (args in memo)
      return memo[args];
    else
      return (memo[args] = func.apply(this, args));

  }
}

使用这个,我做到了

var fib = function(n)
{
  if (n <= 1)
  {
    return 1; // as the Fib definition in Math
  }
  else
  {
    return fib(n - 2) + fib(n - 1); // as the Fib definition in Math
  }
};

log(memoize(fib)(43));
log(fib(43));

但是,我确认没有效果。

我也出于同样的目的尝试了一个 npm 库,

https://github.com/medikoo/memoize

var memoize = require('memoizee');

log(memoize(fib)(43));
log(fib(43));

结果,一样。

我错过了什么,以及如何修复并使其正常工作?

谢谢!

编辑

require('memoizee');

var fib = function(n)
{
  if (n <= 1)
  {
    return 1; // as the Fib definition in Math
  }
  else
  {
    return fib(n - 2) + fib(n - 1); // as the Fib definition in Math
  }
};

var generator = function(f)
{
  return memoize(f);
};

var _fib = generator(fib);
console.log(_fib(40)); //no effect

【问题讨论】:

  • 从您发布的内容来看,只有第一个调用使用了 memoize-d 函数。递归调用都使用原来的fib函数。
  • 哦,当然。我明白了。想着怎么修。谢谢

标签: javascript node.js memoization


【解决方案1】:

memoize 调用不会改变 fib 函数,但会返回其新的、已记忆的对应物。在您的代码中,您只调用了一次,下次调用原始的 fib 函数。您需要创建 一个 记忆的“包装器”,并调用它多次次:

var mFib = memoize(fib);
log(mFib(43));
log(mFib(43));

您也可以覆盖原来的fib = memoize(fib);,这样还有一个额外的好处是递归调用(这是有趣的调用)也会被记住。

【讨论】:

  • 酷。我喜欢过度写作的想法。通常,不建议在声明中这样做,但我的项目是为此的库。所以我会雇用。太好了,谢谢。
  • 由于您通常只需要手动将 memoisation 应用于特定功能,您也可以在他们的声明中这样做:var fib = memoize(function(n) { … fib(n-1) + fib(n-2) … });
  • 谢谢。再想一想,在我的项目中,一个生成器函数实际上负责该函数,在本例中为fib,并完成其余的过程。所以,我不能硬编码在同一范围内覆盖 fib。如果可能的话,我想避免在他们的声明点添加 memoize。对于这种情况,你有什么想法吗?
  • 我知道underscore underscorejs.org/#memoize 按照你现在的建议做,但我想知道是否有任何方法可以在生成器函数中隐藏它。
  • 不,如果您无法访问该范围,那么您无法通过记忆优化(递归调用)函数。但是,如果您无法更改该模块,那么它似乎不是您的理想之选。询问负责它的开发人员。
猜你喜欢
  • 2015-09-05
  • 2020-04-19
  • 2021-12-23
  • 1970-01-01
  • 2022-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多