【问题标题】:Implementing and understanding "memoize" function in underscore & lodash在下划线和 lodash 中实现和理解“memoize”功能
【发布时间】:2015-12-09 04:25:21
【问题描述】:

一直在尝试通过查看下划线文档并尝试编写我自己的更常用函​​数的版本来了解有关函数式编程的更多信息。

遇到“memoize” - 我无法将头绕在它周围,并在 Crockford 的“The Good Parts”中找到了一些信息。

  _.memoize = function(func) {
    // 'cache' object is used to hold the result of the memoized fn's call
    var cache = {};
    var recur = function(n) {
      var result = cache[n];
      if (typeof result === 'undefined') {
        result = func.apply(this, arguments);
        cache[n] = result;
      }
      return result;
    }
    return recur;
  };

您能否帮助我了解我是否有必要使用 .apply,以及我是否可以对这段代码进行任何核心改进?非常感谢您的帮助!

【问题讨论】:

  • 是的,apply 的使用是必要的,因为你不知道func 将有多少个参数
  • 那是你自己写的代码?你有什么不明白的吗?或者下划线的哪些部分你不明白?
  • @Bergi - 我能够找到这个解决方案,但我想看看是否有任何错误或改进。正如我在下面提到的,我已经改变了 typeof 的使用并改用 hasOwnProperty 。但是,我正在尝试弄清楚如何防止 memoized 函数运行超过它需要的次数。
  • 也许这个问题最好在Code Review 提问。不过没关系。

标签: javascript memoization


【解决方案1】:

正确性存在一些明显的问题:

1) 你只根据 first 参数的值缓存结果,所以调用不同参数的函数会产生错误的结果!

let add = memoize((a, b) => a + b)
add(1, 2)
> 3
add(1, 3)
> 3

2) 您使用undefined 表示尚未调用的函数,但undefined 是有效的返回值。看看副作用如何发生两次:

let log = memoize(() => console.log('hello'))
log()
> hello
log()
> hello

您可以改为使用cache.hasOwnProperty 来检测缓存中是否有内容。

我建议您编写一个测试套件。测试对于发现这些错误非常有价值。想想你的功能可能无法正常工作的其他极端情况。像这样的独立实用程序真的很适合测试驱动的编码。

【讨论】:

  • 嘿,非常感谢您的明确答复。这很有帮助。考虑到使用“未定义”仍然可以返回有效的返回值,我继续进行了重构。我用if (!cache.hasOwnProperty(result)) {代替了这条线
  • 想想var log = memoize(console.log.bind(console)); log("hasOwnProperty"); log("hasOwnProperty");
猜你喜欢
  • 2014-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-17
相关资源
最近更新 更多