I'm struggling with an example of js memoization found on a book, here's the code:
Function.prototype.memoized = function(key){
this._values = this._values || {};
return this._values[key] !== undefined ? this._values[key] : this._values[key] = this.apply(this, arguments);
}
here's a fiddle with a complete example
what I don't really get is how this piece of code works and what it does, in particular the apply
part:
return this._values[key] !== undefined ? this._values[key] : this._values[key] = this.apply(this, arguments);
I know and understand how apply
works
The apply() method calls a function with a given this value and arguments provided as an array
suppose that this._values[key]
is equal to undefined
, then the returned value will be this.apply(this, arguments)
: does this code re-launch the memoized
function? I've tried to add some logs inside the function to see how many times the function is called, but it seems it's been launched only once..
Can anyone please give me a hint? It's probably a dummy question, please be patient, thanks
Notes
Since you are attaching
memoized
to theFunction.prototype
, you can invoke thismemoized
on some other function only. Like in your exampleSince you are invoking
memoized
on a function, thethis
will be referring to the function on which thememoized
is invoked. So, in this case,this
refers toisPrime
.Actual explanation
This line makes sure that the
isPrime
has got an attribute with the name_values
and it should have an empty object, if it is not there already.This check is to make sure that we have been already called with
key
or not. If the value is notundefined
, then returnthis._values[key]
.Otherwise,
store the result of calling
this.apply(this, arguments)
inthis._values[key]
and return it. Now the important part.It is straight forward.
arguments
is an array like object. So, If you have actually calledisPrime
like thisisPrime(1, 2, 3, 4)
, arguments will have{'0': 1, '1': 2, '2': 3, '3': 4}
. Now that we are insidememoized
, we need to invokeisPrime
as it was intended to be invoked. So,this.apply(this, arguments)
is done.Function.prototype.apply
, tries to spread the array like object passed as the second parameter, while invoking the function.Let's use a simple example, fibonacci numbers.
Here we can see that the
memoized
method is applied on thefib
function, i.e. yourthis
keyword refers to thefib
function. It does not relaunch thememoized
function, but "launches" the function on which it was called. However, it does call it withthis
set to the function itself, which does not make any sense. Better:Even better would be if
memoized
would return a closure: