![](/img/trans.png)
[英]Explanation on “JavaScript - the Good Parts” memoization example (section 4.15)?
[英]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)
}());
此系統(從自執行匿名函數返回函數)允許您在本地作用域中定義仍可由返回函數使用的變量,但不能由作用域外的函數使用。 這是一個例子 。
由於該函數返回 確實需要一個參數的函數。
要理解這一點,我認為使用一個更簡單的例子是有幫助的。 看看下面的兩個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.