简体   繁体   English

Javascript Memoization解释?

[英]Javascript Memoization Explanation?

Reading an example from a book, can someone explain how the function call to fibonacci takes in the argument 'i' when the function itself doesn't declare any parameters? 从一本书中读取一个例子,有人可以解释当函数本身没有声明任何参数时,函数调用fibonacci如何接受参数'i'吗?

var fibonacci = (function () {
    var memo = [0, 1];
    var fib = function (n) {
        var result = memo[n];
        if (typeof result !== 'number') {
            result = fib(n - 1) + fib(n - 2);
            memo[n] = result;
        }
        return result;
    };
    return fib;
}());

for(var i = 0; i <= 10; i += 1) {
    document.writeln('// ' + i + ': ' + fibonacci(i));
}

You are creating a self-executing anonymous function (function(){}()); 您正在创建一个自执行的匿名函数(function(){}()); which inside it returns the fib function, which takes an argument. 在其中返回fib函数,它接受一个参数。 var fib = function(n){} ... return fib; var fib = function(n){} ... return fib;

var fibonacci = (function () { // Self-executing anonymous function
    var memo = [0, 1];         // local variable within anonymous function
    var fib = function (n) {   // actual fib function (takes one argument)
        var result = memo[n];
        if (typeof result !== 'number') {
            result = fib(n - 1) + fib(n - 2);
            memo[n] = result;
        }
        return result;
    };
    return fib; // return fib (fibonacci is now set to the function fib defined above, which takes one argument)
}());

This system (returning a function from a self-executing anonymous function) allows for you to define variable in a local scope that can still be used by the returned function, but not by functions outside the scope. 此系统(从自执行匿名函数返回函数)允许您在本地作用域中定义仍可由返回函数使用的变量,但不能由作用域外的函数使用。 Here is an example . 这是一个例子

This technique is called closure in JavaScript. 这种技术在JavaScript中称为closure Read more about it on the MDN guide. MDN指南中了解更多相关信息

由于该函数返回 确实需要一个参数的函数。

To understand this, I think it is helpful to work with a simpler example. 要理解这一点,我认为使用一个更简单的例子是有帮助的。 Take a look at the two memoized functions below. 看看下面的两个memoized函数。 The only difference is the () after add : function (){ ... }() on the successful memorization code. 唯一的区别是()add : function (){ ... }()在成功的记忆编码。

    var failed_memoization = {
        add : function (){
            var counter;
            return function(number){
                if(counter){
                    counter = counter + number;
                    return counter;
                }
                counter = number;
                return counter;
            } //NOTE: NO function call brackets here
        }
    }

    var successful_memoization = {
        add : function (){
            var counter;
            return function(number){
                if(counter){
                    counter = counter + number;
                    return counter;
                }
                counter = number;
                return counter;
            }
        }()  //NOTE: the function call brackets here!!
    };
}

Now let's execute these two functions. 现在让我们执行这两个函数。

console.log('Failed Memoization');
console.log(failed_memoization.add(5));      //We wanted 5, but this prints the text of the function instead.... Okay, lets try something else
console.log(failed_memoization.add()(5));    //5
console.log(failed_memoization.add()(10));   //10 (Wanted it to be 5+10 = 15.
console.log('successful_memoization');
console.log(successful_memoization.add(8));  //8
console.log(successful_memoization.add(16)); //24 (This is what we wanted 8 + 16 = 24)

So what's going on here is that for successful_memoization when we put () to the end of its add : function(){...}() . 所以这里发生的是当我们把()放到add : function(){...}()的末尾时,对于successful_memoization As such, this function is executed immediately on the creation of the static object. 因此,在创建静态对象时立即执行此功能。 In turn, executing that function returns the object function (number){...} wich results in the assignment: add : function (number){...} NOT add : function(){} as it initially appears. 反过来,执行该函数会返回导致赋值的对象function (number){...}add : function (number){...} NOT add : function(){}因为它最初出现。

What is also important to note is that var counter is declared outside return function(name){} . 还需要注意的是, var counter return function(name){} 之外声明。 As it is still being used within add : function(number){...} , this variable is accessible within that function. 由于它仍在add : function(number){...} ,因此该变量可在该函数中访问。 For failed_memoization.add()(number) , it uses a new counter each time we execute that function, because we execute the first function, and then the inner function on each call. 对于failed_memoization.add()(number) ,它每次执行该函数时都使用一个新counter ,因为我们执行第一个函数,然后执行每个调用的内部函数。 For successful_memoization.add(number) we executed the outer function upon initialization, and so counter will persist through all subsequent calls and will not be overwritten. 对于successful_memoization.add(number)我们在初始化时执行了外部函数,因此counter将在所有后续调用中保持不变,并且不会被覆盖。

There is a self-calling function that returns the function with the identifier fib which is then assigned to the identifier fibonacci . 有一个自调用函数返回带有标识符fib的函数,然后将其分配给标识符fibonacci This way you can create a private variable memo which is only accessible by the function. 这样您就可以创建一个只能由函数访问的私有变量memo So var fibonacci in fact is function(n){...} . 因此var fibonacci实际上是function(n){...}

var fibonacci = (function() {
    ...
    return fib;
})();

This is a self-executing function. 这是一个自动执行的功能。

It declares a function expression which returns a function ( fib ), executes the outer function expression immediately ( () ), and assigns its return value (which is fib ) to the fibonacci variable. 它声明了一个函数表达式,它返回一个函数( fib ),立即执行外部函数表达式( () ),并将其返回值(即fib )赋给fibonacci变量。

Function fibonacci does take one argument. 功能fibonacci确实有一个论点。 Note that the unnamed function that starts on the first line is not the function that ends up being known as fibonacci . 请注意,从第一行开始的未命名函数不是最终被称为fibonacci的函数。 That unnamed function is immediately called since you have () immediately after closing brace } . 这个匿名函数立即调用,因为你有()右括号后立即} This unnamed function returns fib , a local variable to which a single-argument function is assigned. 这个未命名的函数返回fib ,一个分配了单参数函数的局部变量。 Thus, fibonacci ends up referring to the function returned by the unnamed function, ie fibonacci is this: 因此, fibonacci最终引用了未命名函数返回的函数,即fibonacci是这样的:

var fib = function (n) {
    var result = memo[n];
    if (typeof result !== 'number') {
        result = fib(n - 1) + fib(n - 2);
        memo[n] = result;
    }
    return result;
};

Note that this function refers to local variables of the unnamed function for the purpose of memoizing. 请注意,此函数引用未命名函数的局部变量以进行记忆。

The critical thing to notice was () which calls the unnamed function immediately, here are some examples that illustrate this technique: 需要注意的关键是()它会立即调用未命名的函数,这里有一些示例说明了这种技术:

var a = (function() { return 1; });

Variable a holds a function which returns 1. 变量a包含一个返回1的函数。

var a = (function() { return 1; }());

Here however, variable a holds value 1. 但是,变量a保持值1。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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