Why need apply in memoization function?

2019-07-19 14:50发布

问题:

I've been toyin with concept of memoization and there are obviously different implementations of it. I put this together and it seems to work fine:

Function.prototype.memoized = function(a) {
    debugger
    if (typeof cache === "undefined") cache = [];
    if (cache[a]) {
        return cache[a];
    } else {
        cache[a] = this(a);
        return cache[a];
    }
}

Function.prototype.memoize=function() {
  t=this;
  return function() {
   // Resig seems to use this:
   return t.memoized.apply(t,arguments);
   // why not simple this:
   //return t.memoized(arguments[0]);
  }

}

myTest = (function fibonacci(n) {

    return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}).memoize();

console.log(myTest(2));

My question is however why in some implementations I see return t.memoized.apply(t,arguments); rather than simple return t.memoized(arguments[0]); inside of proptotype.memoize? I cannot see any advantage apart from passing multiple arguments which are not used anyway. I there any advantage to apply?

EDIT:

Updated the code and I believe this takes care of major problems so cache as global on window (what was I thinking??) and recursive fibonacci not memoizing calls to itself. Are there any other major issue with my implementation?

Function.prototype.memoized = function(a) {

    if (typeof this.cache === "undefined")  this.cache = [];
    if (this.cache[a]) {
        return this.cache[a];
    } else {
        this.cache[a] = this(a);
        return this.cache[a];
    }
}

Function.prototype.memoize=function() {
  t=this;
  return function() {
   //return t.memoized.apply(t,arguments);
   return t.memoized(arguments[0]);
  }

}

myTest = (function fibonacci(n) {
    //return a * 3;

    return n < 2 ? n : fibonacci.memoized(n - 1) + fibonacci.memoized(n - 2);
}).memoize();

console.log(myTest(2));

BTW this is learning experience for me and doing it purely for fun, it's not assignment or anything like that uni related.

回答1:

In general, JavaScript functions are variadic, which means that you would need to pay attention to all of them actually. Some memoize implementations do this by using JSON.stringify(arguments) for the cache key.


In this case, it does not make any sense, since the memoized method does only use a single argument as well.

However, there are more serious bugs in your code than this little inaccuracy. cache is a global variable, while it should be bound to the specific memoized function. Also, your fib implementation is not memoized in the recursive call, where it actually is the most important.


The edited version looks good (except for the global t variable). In personal, I would have shortened/simplified the code a little bit however:

Function.prototype.memoize=function() {
    var t = this;
    this.cache = [];
    return function(a) {
        var cache = t.cache;
        if (typeof cache[a] == "undefined")
            cache[a] = t(a);
        return cache[a];
    };
}

var fibonacci = (function (n) {
    return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}).memoize();

console.log(fibonacci(2));