Reputation: 559
I am trying to solve this problem.
Sample code from Secrets of the Javascript Ninja:
Function.prototype.memoized = function(key){
this._values = this._values || {};
return this._values[key] !== undefined ?
this._values[key] :
this._values[key] = this.apply(this, arguments);
};
function isPrime( num ) {
var prime = num != 1;
for ( var i = 2; i < num; i++ ) {
if ( num % i == 0 ) {
prime = false;
break;
}
}
return prime;
}
alert(isPrime.memoized(5);
This code gives us a convenient way of adding functionality, by adding a function to the Function prototype.
However, the "this" reference gets messed up, if I convert this function to use an object in Javascript:
JSFiddle link:https://jsfiddle.net/vcqqc8a8/3/
function Test() {
this.testVar = 2;
};
Test.prototype.isPrime = function (num) {
alert(this.testVar); // This works, when isPrime is called through obj.isPrime(), but not when its called through memoized()
var prime = num != 1;
for ( var i = 2; i < num; i++ ) {
if ( num % i == 0 ) {
prime = false;
break;
}
}
return prime;
};
var t = new Test();
t.isPrime(5); // "this" inside Test.prototype.isPrime is correctly set to "t"
t.isPrime.memoized(5); // "this" inside Test.prototype is set to isPrime (expected behavior, but I want it to be preserved to "t').
The problem is that "this" is changed to the caller, so in the case of the second call (t.isPrime.memoized(5)), "this" is set to isPrime, which causes memoized to correctly call isPrime. However, when isPrime is actually called, I want "this" to correctly become "t".
Is there anyway to achieve this?
Upvotes: 1
Views: 84
Reputation: 664444
You can use
t.isPrime = t.isPrime.bind(t);
t.isPrime.memoized(5);
or you fix memoized
to pass the appropriate this
. And not to store its cache values on the function, which won't really work for a prototype where the method is shared but usually each instance needs its own cache.
Upvotes: 2