JavaScriptclosures困惑

→jsFiddle

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?

每次调用f1() ,都会使用自己的本地nvariables创build一个新的闭包。

然而, nAddvariables是全局variables,因此每次调用f1()时都会被覆盖 – 这意味着调用nAdd()只会添加到最后一个闭包中的nvariables中。

更新:如果你想能够独立地增加每个闭包中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()返回一个包含两个未声明为全局variables的方法的对象,并且这两个方法都是在它们所属的闭包的本地nvariables上进行操作的。

已经有了很好的答案,但是我猜想一张图片会有助于理解。

在这里输入图像说明

每次你打电话给f1()你:

  • 创build一个名为n的新(本地)variables,值为999
  • 创build一个新的分配给全局 nAdd无名函数,修改n (并覆盖任何先前分配给nAdd函数)
  • 创build一个新的函数,返回哪个警报n的值

你调用f1()两次,所以你做了两次。 第二次调用它时,你nAdd用一个修改第二个 n的新函数覆盖nAdd

这给你留下了:

  • result()提醒第一个 n
  • result2()提醒第二个 n
  • nAdd()增加第二个 n

最后一行的result()提示999因为它会提醒 n值(从未递增)。

resultresult2包含f1不同调用的结果,因此包含局部variablesn不同实例。 函数的每个调用对于该函数的局部variables可能具有不同的值。 甚至在没有closures时也适用。

nAdd=function(){n+=1;}; 行创build一个全局函数,它是f1()一个闭包。 闭包也可以访问创build它的函数的范围。 所以每次调用f1() ,都会创build一个新的nAdd()函数,该函数的n值绑定到f1()调用的var n的值。

在你的代码中;

 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 

结果和结果2创build两个不同的nclosures。 如果通过在f1()函数之外声明它来使得全局variables为na,那么您将得到您所期望的结果,因为在这种情况下,您将始终访问全局variablesn:

var n = 999; 函数f1(){
n添加=函数(){N + = 1;};
函数f2(){
的console.log(N);
}
返回f2;
}
var result = f1();
var result2 = f1();
结果(); // 999
n添加();
RESULT2(); // 1000
RESULT2(); // 1000
结果(); // 1000

它是这样的:

 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