Javascript回忆录解释?
阅读一本书中的一个例子,有人能解释一下当函数本身没有声明任何参数时,对fibonacci的函数调用是如何接受参数“i”的吗Javascript回忆录解释?,javascript,Javascript,阅读一本书中的一个例子,有人能解释一下当函数本身没有声明任何参数时,对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) +
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));
}
var fibonacci=(函数(){
var memo=[0,1];
var fib=函数(n){
var结果=备忘录[n];
如果(结果类型!=='number'){
结果=fib(n-1)+fib(n-2);
备注[n]=结果;
}
返回结果;
};
返回fib;
}());
对于(var i=0;i
这是一个自动执行的函数
它声明一个函数表达式,该表达式返回一个函数(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。因为函数返回的函数不带参数。您正在创建一个自动执行的匿名函数(function(){}());
它在其中返回fib
函数,该函数带有一个参数。var fib=function(n){}
…返回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
。请在上阅读更多有关此技术的信息。有一个自调用函数,它返回带有标识符fib
的函数,然后将该标识符赋给标识符fibonacci
。这样,您可以创建一个只有t才能访问的私有变量memo
函数。因此var fibonacci
实际上是function(n){…}
为了理解这一点,我认为使用一个更简单的例子是很有帮助的。看看下面的两个记忆函数。唯一的区别是后的()
在成功的记忆代码上添加: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(){…}()
的末尾时。同样地,这个函数在创建静态对象时立即执行。反过来,执行该函数返回对象function(number){…}
这将导致赋值:add:function(number){…}
不是最初出现的add:function(){}
还需要注意的是,var计数器
在return function(name){}
外部声明为。由于它仍在add:function(number){…}
中使用,因此该变量可在该函数中访问。对于失败的记忆。add()(number)
,每次执行该函数时,它都会使用一个新的计数器,因为我们在每次调用时先执行第一个函数,然后执行内部函数。对于成功的记忆。添加(数字)
我们在初始化时执行了外部函数,因此计数器将在所有后续调用中保持不变,并且不会被覆盖。值得注意的是,内部函数即使在outter函数返回后也访问outter函数上的变量的技术称为闭包这本书是Javascript的好部分,对过程有更好的描述。
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)