【问题标题】:Memoization javascript记忆javascript
【发布时间】:2017-12-04 10:07:47
【问题描述】:

我正在从 JavaScript: The Good Parts 一书中学习 JavaScript,在 memoization 部分有一个关于使用 memoize 技术解决斐波那契问题的示例

我们创建一个通用函数调用memoizer,它接受一个备忘录数组和基本函数,返回一个管理备忘录并调用基本函数的shell函数

 var memoizer = function(memo, fundamental) {
  var shell = function(n) {
    var result = memo[n];
    if (typeof result !== 'number') {
      result = fundamental(shell, n);
      memo[n] = result;
    }
    return result;
  };
  return shell;
};

然后像这样创建斐波那契:

var fibonacci = memoizer([0, 1], function(shell, n) {
    return shell(n-1) + shell(n-2);
});

如果我运行 fibonacci(10),结果将准确显示。

但让我困惑的是memoizer函数中的n参数shell函数。我知道这是我们要计算的值。但它来自哪里?如何调用 fibonacci(10),例如,可以将值 10 传递给 n? var fibonacci 究竟是什么?是函数还是作为memoizer指向函数对象?

感谢您的帮助!

【问题讨论】:

  • fibonacci 是一个由memoizer 返回的函数。
  • 你的意思是fibonaccishell返回的函数memoizer?那么我们传给fibonacci的值也传给了shell函数中的n?
  • fibonacci 的参数或shell 的参数被传递给fundamental 回调
  • 顺便说一句:fib(100) 354224848179262000000 的天真实现返回,尽管正确的值是 354224848179261915075。浮点数对于计算斐波那契数来说非常次优。如果数字类型甚至不能处理很小的值,那么记忆化的好处,即能够计算出真正的大数字,就已经过时了。

标签: javascript memoization


【解决方案1】:

因此,要完全理解这一点,您需要将以下内容理解为基本部分。



那么,现在看一下代码。
var memoizer 被分配为一个函数,它在内部返回另一个函数。

var memoizer = function(memo, fundamental) {
  var shell = function(n) {
    ... do some works ...
  };
  return shell;
};

你能看到吗? var shellmemoizer 的行尾返回


无论memoizer中的内部逻辑是什么,它的结果都分配给var fibonacci

var fibonacci = memoizer([0, 1], function(shell, n) {
    return shell(n-1) + shell(n-2);
});


所以,这意味着fibonacci 等于memoizer 的结果(因为我们执行了它),而memoizer 的结果等于shell 函数。如果你仔细阅读我给你的那些链接,你就会明白幕后发生了什么。

顺便说一句,您提供的代码并不是最好的方法。因为无论如何 closure 都会使激活的对象活着,而这是不必要的。

下面的代码是另一种制作斐波那契的方法,这不是绝对最好的方法,但是,我建议您将此代码与您的代码进行比较,找出差异。

var result = [];
result[0] = 1;
result[1] = 1;

function fibonacci(n){
    var i;
    
    for(i = 2; i < n; i++){
      if(!result[i]){
        result[i] = result[i-1] + result[i-2];
      }
    }
    return result[i-1];
}

console.log(fibonacci(10));

【讨论】:

  • "不管怎样,闭包使激活的对象活着,这不是必需的。" - 什么?
  • 当你使用闭包时,外部激活的对象必须是活动的,因为内部仍然引用它
  • 当然,但这有什么问题?为了获得记忆的好处,关闭记忆图是非常必要的。
  • @Bergi 哦,我的意思是,在这种情况下,还有另一种很好的方法可以在不使用闭包的情况下实现该逻辑。我的思路已经很开阔了。我想告诉那个询问使用没有明确目的的闭包的人会导致内存泄漏。就像我提供的代码一样,它也使用了没有闭包的记忆。因此,如果您无论如何都应该通过使用 memoization 来实现该逻辑,那么避免闭包不是更好吗
  • @Bergi 好吧,在该代码中调用 result 也是一种闭包 :( 是的,那么也许来自提问者的代码会更好
猜你喜欢
  • 2013-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多