在 JavaScript 中实现自动记忆(返回闭包函数)

问题描述 投票:0回答:2

我读过

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
javascript node.js memoization
2个回答
3
投票

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

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

您还可以覆盖原来的

fib = memoize(fib);
,这还有一个额外的好处,即递归调用(有趣的调用)也将被记住。


0
投票

主要问题是内部递归调用不会调用原始函数,导致记忆功能无法按预期工作。如果我们可以使原始函数将附加参数作为相同的函数引用,它将简化。

// adding "fib" as additional argument
function fib(n, fib) {
  if (n < 2) {
    return n;
  }
  return fib(n - 1) + fib(n - 2);
}

function memoize(fn, argIndex = 0) {
  const track = {};
  return function memFn(...args) {
    if (args[argIndex] in track) {
      console.log("cached value - ", args[argIndex]);
      return track[args[argIndex]];
    }
    console.log("actual call - ", args[argIndex]);
    return (track[args[argIndex]] = fn.call(this, ...args, memFn));
  };
}

const memFib = memoize(fib);

memFib(6);

对于我们无法访问原始函数的场景(在本例中为 fib),我们可以使用

Function
构造函数将原始函数的包装函数添加为具有附加参数。

function memoize(fn, argIndex = 0) {
  const track = {};
  const wrapFn = new Function(
    "return " + fn.toString().replace(")", `,${fn.name})`),
  )();
  return function memFn(...args) {
    if (args[argIndex] in track) {
      console.log("cached value - ", args[argIndex]);
      return track[args[argIndex]];
    }
    console.log("actual call - ", args[argIndex]);
    return (track[args[argIndex]] = wrapFn.call(this, ...args, memFn));
  };
}

function fib(n) {
  if (n < 2) {
    return n;
  }
  return fib(n - 1) + fib(n - 2);
}

const memFib = memoize(fib);

const result = memFib(6)

© www.soinside.com 2019 - 2024. All rights reserved.