簡體   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