[英]doubts on javascript apply - function memoization
I'm struggling with an example of js memoization found on a book, here's the code: 我正在努力寻找一本书中的js记忆示例,下面是代码:
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: 我没有真正得到的是这段代码的工作方式及其作用,特别是
apply
部分:
return this._values[key] !== undefined ? this._values[key] : this._values[key] = this.apply(this, arguments);
I know and understand how apply
works 我知道并了解
apply
The apply() method calls a function with a given this value and arguments provided as an array
apply()方法调用具有给定值的函数,并以数组形式提供参数
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? 假设
this._values[key]
等于undefined
,那么返回的值将是this.apply(this, arguments)
:该代码是否重新启动了memoized
功能? 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
这可能是一个假问题,请耐心等待,谢谢
Let's use a simple example, fibonacci numbers. 让我们使用一个简单的例子斐波那契数。
function fib(n) {
if (n < 2) return 1;
return fib.memoized(n-1) + fib.memoized(n-2);
}
Here we can see that the memoized
method is applied on the fib
function, ie your this
keyword refers to the fib
function. 在这里,我们可以看到
memoized
方法适用于fib
函数,即您的this
关键字引用了fib
函数。 It does not relaunch the memoized
function, but "launches" the function on which it was called. 它不会重新启动已
memoized
功能,而是“启动”被调用的功能。 However, it does call it with this
set to the function itself, which does not make any sense. 但是,它与调用它
this
集函数本身,这并没有任何意义。 Better: 更好:
Function.prototype.memoize = function(key){
if (!this._values)
this._values = {};
if (key in this._values)
return this._values[key];
else
return this._values[key] = this.apply(null, arguments);
// pass null here: ^^^^
}
Even better would be if memoized
would return a closure: 更好的是,如果
memoized
将返回关闭:
Function.prototype.memoized = function(v) {
var fn = this, // the function on which "memoized" was called
values = v || {};
return function(key) {
if (key in values)
return values[key];
else
return values[key] = fn.apply(this, arguments);
}
}
var fib = function(n) {
if (n < 2) return 1;
return fib(n-1) + fib(n-2);
}.memoized();
// or even
var fib = function(n) { return fib(n-1) + fib(n-2) }.memoized({0:1, 1:1});
Notes 笔记
Since you are attaching memoized
to the Function.prototype
, you can invoke this memoized
on some other function only. 由于将
memoized
在Function.prototype
,因此memoized
在其他函数上调用该memoized
。 Like in your example 就像你的例子
isPrime.memoized(5)
Since you are invoking memoized
on a function, the this
will be referring to the function on which the memoized
is invoked. 既然你调用
memoized
上的功能,在this
将参照在其上的功能memoized
被调用。 So, in this case, this
refers to isPrime
. 因此,在这种情况下,
this
是指isPrime
。
Actual explanation 实际说明
this._values = this._values || {};
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. 此行确保了
isPrime
已经得到了与该名称的属性_values
,它应该有一个空的对象,如果不存在的话。
this._values[key] !== undefined
This check is to make sure that we have been already called with key
or not. 进行此检查是为了确保已经使用
key
调用了我们。 If the value is not undefined
, then return this._values[key]
. 如果该值
undefined
,则返回this._values[key]
。
Otherwise, 除此以外,
this._values[key] = this.apply(this, arguments)
store the result of calling this.apply(this, arguments)
in this._values[key]
and return it. 将调用
this.apply(this, arguments)
的结果存储在this._values[key]
并返回它。 Now the important part. 现在重要的部分。
this.apply(this, arguments)
It is straight forward. 很简单。
arguments
is an array like object. arguments
是一个类似于对象的数组。 So, If you have actually called isPrime
like this isPrime(1, 2, 3, 4)
, arguments will have {'0': 1, '1': 2, '2': 3, '3': 4}
. 因此,如果您实际上像
isPrime(1, 2, 3, 4)
这样调用isPrime
,则参数将具有{'0': 1, '1': 2, '2': 3, '3': 4}
。 Now that we are inside memoized
, we need to invoke isPrime
as it was intended to be invoked. 现在,我们在里面
memoized
,我们需要调用isPrime
,因为它的目的是要被调用。 So, this.apply(this, arguments)
is done. 这样,
this.apply(this, arguments)
就完成了。 Function.prototype.apply
, tries to spread the array like object passed as the second parameter, while invoking the function. Function.prototype.apply
,在调用该函数时,尝试像作为第二个参数传递的对象一样散布数组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.