Reputation: 111
I'm reading Javascript Ninja from John Resig, and there is this one concept mentioned in Memoization chapter which I can't figure out how it works. And I'm having trouble finding an explanation on Google. So, here is the example from the book.
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.prototype.memoize = function(){
var fn = this;
return function(){
return fn.memoized.apply( fn, arguments );
};
};
var isPrime = (function(num) {
var prime = num != 1;
for (var i = 2; i < num; i++) {
if (num % i == 0) {
prime = false;
break;
}
}
return prime;
}).memoize(); // I don't understand how this works
Now, I understand how closure works in this example, and I understand prototypes in general, but I don't understand how this (function expression).memoize()
part works? I see that memoize returns a function, and that function (I presume) is added to isPrime
, but how does this (function expression)
get called, or how does it fit in as part of isPrime method? So, when I call isPrime(17)
, what is executed first?
Edit: Ok, I'm now confused from all the commants, so here is how I now see it.
First: When (function(num){....}).memoize()
gets called, the anonymous function expression (function(num){...})
is represented as this
in the memoize function and assigned to fn.
Second: Inside memoize an anonymous function is returned which holds fn
via a closure. That returned anonymous function is assigned to isPrime
Third: When we call isPrime(17)
, actually what is called is fn.memoized.apply(fn, attributes)
, and inside memoized this
(the context) represents fn which is a reference to the anonymous function (function(num{...})). And this part: this.apply(this, arguments)
executes that anonymous function (function(num) {...})
Which makes sense, first a check needs to be made if the number is cached, and if not check if it is prime and put it in the cache.
Upvotes: 1
Views: 161
Reputation:
The following happens:
Function
prototype is extended with two methods memoized
and memoize
(however, extending native prototypes isn't recommended)(function(num)...
is assigned to isPrime
memoize
of the Function prototype is invokedmemoize
this
is automatically bound to the object the method is called on (the function object in this case). So this
refers to the anonymous function, which later is assigned to isPrime
. Finally a thunk return function(){...
is returned to defer the execution.apply
to pass an arbitrary number of arguments to memoized
(note that the first argument provided to memoized
is used as a key for the memoizing cache)I consider this implementation ugly, because amongst other things it obscures the fact that not the original anonymous function is assigned to isPrime
, but the thunk that wraps it.
I'm not sure if isPrime
(or the anonymous function expression) is an IIFE, since merely the method of its prototype is called immediately, not the function itself.
Upvotes: 1