function f1(){
var n=999;
nAdd=function(){n+=1;};
function f2(){
alert(n);
}
return f2;
}
var result = f1();
var result2 = f1();
result(); // 999
nAdd();
result2(); // 1000
result2(); // 1000
result(); // 999
我正在尝试学习JavaScript闭包,但上面的代码让我感到困惑。
当第一次调用result()
时,它是999.这对我来说没问题。
调用nAdd()
后,result2()
显示1000.我认为这是由于函数result2()
和函数result()
等于函数f1()
。
但为什么最后result()
显示999而不是1000?
答案 0 :(得分:36)
每次调用f1()
时都会创建一个带有自己的本地n
变量的新闭包。
但是,nAdd
变量是全局的,因此每次调用f1()
时都会被覆盖 - 这意味着调用nAdd()
只会添加到n
变量中最后关闭。
更新:如果您希望能够独立增加每个闭包中n
的值,您可以执行以下操作:
function f1(){
var n=999;
return {
incrementN : function(){n+=1;},
getN : function f2(){console.log(n);}
}
}
var result = f1();
var result2 = f1();
result.getN(); // 999
result.incrementN();
result2.getN();//999
result2.incrementN();
result2.getN();//1000
result.getN();//1000
也就是说,让f1()
返回一个包含两个未声明为全局变量的方法的对象,并且它们都对它们所属的闭包中的本地n
变量进行操作。
答案 1 :(得分:27)
已经有了很好的答案,但我想一张照片有助于理解。
答案 2 :(得分:13)
每次致电f1()
时:
n
的新(本地)变量,其值为999
nAdd
,修改n
(并覆盖分配给nAdd
的所有先前功能)n
你拨打f1()
两次,所以你做了两次这样的事情。第二次调用它时,用一个修改第二个 nAdd
的新函数覆盖n
。
这会让你:
result()
提醒第一个 n
result2()
提醒第二个 n
nAdd()
增加秒 n
result()
提醒999
,因为它会提醒第一个 n
(从未增加过)的值。
答案 3 :(得分:4)
result
和result2
包含f1
的不同调用的结果,因此包含局部变量n
的不同实例。函数的每次调用对于该函数的局部变量可以具有不同的值。这甚至适用于没有涉及闭包的情况。
答案 4 :(得分:1)
nAdd=function(){n+=1;};
行创建一个全局函数,它是f1()
内的闭包。闭包也可以访问创建它的函数范围内的所有变量。因此,每次拨打f1()
时,它都会创建一个新的nAdd()
函数,其n
值绑定到var n
调用的f1()
值。
在您的代码中;
var result = f1();
var result2 = f1();
result(); // 999
nAdd(); // Created by "var result2 = f1();" and has the same 'n' value as function in result2
result2();//1000
result2();//1000
result();//999
答案 5 :(得分:0)
结果和result2创建两个不同的闭包。如果你通过在f1()函数之外声明它来使n成为全局变量,那么你将获得你所期望的结果,因为在这种情况下你将始终访问全局变量n:
var n = 999; function f1(){
n添加=函数(){N + = 1;};
function f2(){
的console.log(N);
}
返回f2;
}
var result = f1();
var result2 = f1();
结果(); // 999
n添加();
RESULT2(); // 1000
RESULT2(); // 1000
结果(); // 1000
答案 6 :(得分:0)
var nAdd;
function f1(){
var n=999;
nAdd=function(){n+=1;};
function f2(){
alert(n);
}
return f2;
}
var result = f1();//var nAdd=function(){n+=1;} n=result.n=999
var result2 = f1();//var nAdd=function(){n+=1;} n=result2.n=999
var result3 = f1();//var nAdd=function(){n+=1;} n=result3.n=999
nAdd();
result(); // 999
result2(); // 999
result3(); // 1000
var result = f1();//var nAdd=function(){n+=1;} n=result.n=999
var result2 = f1();//var nAdd=function(){n+=1;} n=result2.n=999
nAdd();
var result3 = f1();//var nAdd=function(){n+=1;} n=result3.n=999
result(); // 999
result2(); // 1000
result3(); // 999
var result = f1();//var nAdd=function(){n+=1;} n=result.n=999
var result2 = f1();//var nAdd=function(){n+=1;} n=result2.n=999
nAdd();
var result3 = f1();//var nAdd=function(){n+=1;} n=result3.n=999
nAdd();
nAdd();
nAdd();
result(); // 999
result2(); // 1000
result3(); // 1002