3

我正在尝试使用 memoization 来加速我的 Javascript,但我需要它在一个proto方法上,并且我需要所说的方法来访问该this对象,它让我很适合。这是我所拥有的:

MyObj.prototype.myMethod = function(){
    var self = this
        , doGetData = (function() {
            var memo = []
            , data = function(obj) {
                var result = memo;
                if (obj.isDirty) {
                    obj.isDirty = false;
                    result = $.map(obj.details, function(elem, i) {
                        return elem.export();
                    });   
                    memo = result;                      
                }
                return result;
            }
            return data;            
        }())
    ;
    return doGetData(self);
};

我可以让它运行,但我无法让它记忆。我知道出了点问题,但我不知道是什么。我知道有很多关于如何记忆的例子,但我遇到的没有一个像这样处理范围。

4

2 回答 2

1

如果您想要原型上的函数,但您希望它独立地为每个实例进行记忆,那么“备忘录”需要是一个实例属性(或者闭包可以是实例属性,我猜;无论哪个)。

MyObj.prototype.myMethod = function() {
  if (!("memo" in this) || this.isDirty) {
    this.isDirty =false;
    this.memo = $.map(obj.details, function(elem, i) {
       return elem.export();
    });
  }
  return this.memo;
};

我认为你不能在不污染实例的情况下做到这一点,尽管你可以使用更新的 JavaScript 特性来防止“备忘录”的东西被枚举。毕竟,原型由所有实例共享。

于 2013-05-30T23:56:08.693 回答
0

可以使用 Map 对象来存储和检索所有实例的方法缓存。地图支持对象作为键。(有点离题,但严格的模式会影响“this”的传播。现在这在没有“var self = this;”的情况下也可以工作。)

"use strict";
MyObj.prototype.myMethod = function() {
    var prototypeCache = new Map();
    return function(arg) {
        if (!prototypeCache.has(this)) prototypeCache.set(this, new Map());
        var instanceCache = prototypeCache.get(this);
        if (instanceCache.has(arg)) return instanceCache.get(arg);
        else {
            //Do expensive calculation that is stored in result...
            instanceCache.set(arg, result);
            return result;
        }                
    };
}();

现在为简单起见,我还为 instanceCache 使用了 Map。对于速度,通常只使用一个对象。这取决于一个人可以制作的钥匙。通常可以找到一种通过唯一字符串进行存储的方法。(数字可以转换,对象可以有 id 字符串和状态/版本属性,多个参数可以连接成一个字符串...)

另一个完全的解决方案是在构造函数中创建方法,而不是在原型中。但这与在实例属性中使用方法缓存一样严重。更糟糕的是,我想。

于 2017-07-27T20:47:07.280 回答