【问题标题】:generic memoization approach in JavascriptJavascript中的通用记忆方法
【发布时间】:2016-02-12 16:10:43
【问题描述】:

我了解许多通用的记忆方法依赖于对参数列表进行字符串化并将其用作键。例如。如:

Function.prototype.memoized = function() {
    this._values = this.values || {};
    var fn = this;
    return function() {
        var key = JSON.stringify( Array.prototype.slice.call(arguments) );
        if (fn._values[key]===undefined) {
            fn._values[key]=fn.apply(this, arguments);
        }
        return fn._values[key];
    };
};

当尝试记忆“成员函数”时,这显然会失败,因为还必须对上下文进行 JSON 字符串化,即将其视为隐式传递的参数。但是,当上下文是全局对象或同样深的对象或以与函数本身无关的各种方式发生变化时,这不会很好地工作。

但即使我们坚持使用非“成员函数”,也不一定总能完成传递的参数列表,对吧?

三个问题:

  1. 我是否正确理解以通用方式记忆成员函数是没有意义的?
  2. 我是否正确理解,由于无法/不切实际地完全字符串化任何可能的参数列表,以通用方式记忆甚至非成员函数也是不可能的?
  3. 如果 2 成立,那么为什么这么多书籍和博客试图在 Function.prototype 中定义一个通用的 memoize 函数?有什么意义?

【问题讨论】:

  • “字符串化上下文”是什么意思?如果您指的是对象的状态,那么它是没有意义的。记忆特别适用于参数。
  • 至于第二点,确实并非所有可能的值都可以正确字符串化,但大多数都可以。但是,记忆化通过为一组参数创建一个唯一标识符来工作。字符串化是一种常用的方法,但只要你能创建一个唯一的标识符,你就可以记住它。

标签: javascript memoization


【解决方案1】:

方法是带有this 作为副作用来源的函数。您可能知道具有副作用的函数不能被记忆,因为这些效果不依赖于记忆所依赖的方法的参数列表。

但当然有一种解决方法。我们可以手动指定方法所依赖的那些属性,而不是序列化整个对象(由this 引用):

function memoize(f, deps) {
  let cache = {};

  return function(...args) {
    let key = JSON.stringify([deps(), args]), v;
    return cache[key] || (v = f.apply(this, args), cache[key] = v, v);
  };
}

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;

  this.fullName = memoize(
    function(title) { // memoized function
      console.log('memoizing...');
      return title + ' ' + this.firstName + ' ' + this.lastName;
    },
    function() { // dependencies
      return [this.firstName, this.lastName];
    }.bind(this));
}

let person = new Person('Jane', 'Doe');

// initial call
console.log(person.fullName('Ms.')); // memoizing...Ms. Jane Doe

// successive call
console.log(person.fullName('Ms.')); // Ms. Jane Doe

这只是一个概念验证,并非经过全面优化和测试的解决方案。所有功劳归In Lehman's Terms


对于您的问题:

  1. 如果一种方法的计算成本非常高,因此需要手动定义其隐式依赖项(this),那么它可能有用
  2. 是的,有时这是不可能的,但为什么要完全放弃一个几乎通用的解决方案?
  3. 不知道!旅鼠? :D

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-17
    • 2013-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-03
    相关资源
    最近更新 更多