简体   繁体   English

对javascript的疑惑适用-函数记忆

[英]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 笔记

  1. Since you are attaching memoized to the Function.prototype , you can invoke this memoized on some other function only. 由于将memoizedFunction.prototype ,因此memoized在其他函数上调用该memoized Like in your example 就像你的例子

     isPrime.memoized(5) 
  2. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM