2010-04-18 89 views
4

當我正在閱讀書籍Javascript:The Good Parts。我不明白這塊代碼波紋管:Javascript關閉問題

我們可以通過進行 功能可以讓我們memoized 功能概括這一點。 memoizer功能將 採取初始備忘錄陣列和 基本功能。它返回一個 shell函數,該函數管理備忘錄 存儲,並根據需要調用基本函數 函數。我們通過殼 函數和函數的參數 的基本功能:

var memoizer = function (memo, fundamental) { 
    var shell = function (n) { 
     var result = memo[n]; 
     if (typeof result !== 'number') { 
      result = fundamental(shell, n); 
      memo[n] = result; 
     } 
     return result; 
    }; 
    return shell; 
}; 

現在,我們可以用 memoizer定義斐波那契數,提供初始備忘錄 陣列和基本功能:

var fibonacci = memoizer([0, 1], function (test, n) { 
    return test(n - 1) + test(n - 2); 
}); 

我的問題是什麼是測試功能?它什麼時候被定義和調用?這對我來說似乎很困惑。另外我認爲這種說法:memo[n] = result;是無用的。如果我錯了,請糾正。

+0

哇。作爲一個功能很少的編程知識的人,這段代碼讓我大開眼界。這太聰明瞭! – dmb 2010-04-18 03:00:19

+0

相關:[關於「JavaScript - 良好部件」示例(第4.15節)的說明?](https://stackoverflow.com/questions/3798858/explanation-on-javascript-the-good-parts-example-section-4 -15) – Bergi 2014-05-30 13:57:08

回答

1

語句memo[n] = result;將新計算的數字存儲在記憶數組或緩存中。 test函數是要被記憶的函數的參數,並且由memoizer定義和傳遞。調用時,它會檢查要計算的值是否已被緩存。如果是這樣,它從緩存中返回它。否則,它會再次重新計算。

執行上述所有代碼之後,我們得到的記憶是這樣的(但與memo陣列和orig_fibonacci封裝):

var memo = [0, 1]; 

function fibonacci(n) { 
    var result = memo[n]; 
    if (typeof result != 'number') { 
    result = orig_fibonacci(n); 
    memo[n] = result; 
    } 
    return result; 
} 

function orig_fibonacci(n) { 
    return fibonacci(n - 1) + fibonacci(n - 2); 
} 
4

這是一個有趣的代碼片段閱讀:)

您可能知道memoization正在存儲函數的結果,所以下次調用該函數時,它不必計算答案,只需查看它即可。

所以我們需要存儲fibonacci函數的答案,它接受一個int並返回一個int。

var fibonacci = memoizer([0, 1], function (test, n) { 
    return test(n - 1) + test(n - 2); 
}); 

使用初始備忘錄數組調用memoizer,映射fib(0) - > 0和fib(1) - > 1。

其餘的定義了一個未命名的函數,它帶有一個函數和一個數字。 '測試'是一個壞名字,它應該是「recursive_fibonacci_helper」:)

這個未命名的函數成爲「基本」參數。 memoizer函數返回一個函數(shell),它接受一個int參數。這最終成爲斐波納契函數。

所以當有人說「斐波那契(5)」。他們真的叫「殼(5)」。關於關閉的重要部分是「基本」和「備忘錄」已經綁定。

那麼'shell'是做什麼的?

它在備忘錄表中查找它是否已經爲該輸入計算出答案。如果它看到一個答案(=='數字'),那麼它會返回它。否則,它會計算它並將其存儲在備忘錄表中。 memo[n] = result實際上是將計算結果存儲在記憶表中。