繁体   English   中英

Javascript Memoization解释?

[英]Javascript Memoization Explanation?

从一本书中读取一个例子,有人可以解释当函数本身没有声明任何参数时,函数调用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));
}

您正在创建一个自执行的匿名函数(function(){}()); 在其中返回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)
}());

此系统(从自执行匿名函数返回函数)允许您在本地作用域中定义仍可由返回函数使用的变量,但不能由作用域外的函数使用。 这是一个例子

这种技术在JavaScript中称为closure MDN指南中了解更多相关信息

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

要理解这一点,我认为使用一个更简单的例子是有帮助的。 看看下面的两个memoized函数。 唯一的区别是()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!!
    };
}

现在让我们执行这两个函数。

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)

所以这里发生的是当我们把()放到add : function(){...}()的末尾时,对于successful_memoization 因此,在创建静态对象时立即执行此功能。 反过来,执行该函数会返回导致赋值的对象function (number){...}add : function (number){...} NOT add : function(){}因为它最初出现。

还需要注意的是, var counter return function(name){} 之外声明。 由于它仍在add : function(number){...} ,因此该变量可在该函数中访问。 对于failed_memoization.add()(number) ,它每次执行该函数时都使用一个新counter ,因为我们执行第一个函数,然后执行每个调用的内部函数。 对于successful_memoization.add(number)我们在初始化时执行了外部函数,因此counter将在所有后续调用中保持不变,并且不会被覆盖。

有一个自调用函数返回带有标识符fib的函数,然后将其分配给标识符fibonacci 这样您就可以创建一个只能由函数访问的私有变量memo 因此var fibonacci实际上是function(n){...}

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

这是一个自动执行的功能。

它声明了一个函数表达式,它返回一个函数( fib ),立即执行外部函数表达式( () ),并将其返回值(即fib )赋给fibonacci变量。

功能fibonacci确实有一个论点。 请注意,从第一行开始的未命名函数不是最终被称为fibonacci的函数。 这个匿名函数立即调用,因为你有()右括号后立即} 这个未命名的函数返回fib ,一个分配了单参数函数的局部变量。 因此, 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;
};

请注意,此函数引用未命名函数的局部变量以进行记忆。

需要注意的关键是()它会立即调用未命名的函数,这里有一些示例说明了这种技术:

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

变量a包含一个返回1的函数。

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

但是,变量a保持值1。

暂无
暂无

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

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