var addCount;
function s1() {
var count = 0;
addCount = function() {
count++;
};
function s12() {
console.log(count)
}
return s12
}
var result1 = s1();
var result2 = s1();
addCount();
result1(); // count = 0;
result2(); // count = 1;
In the picture I marked the puzzled place 然后,下一步将以这种方式显示 This is where I am really puzzled
答案 0 :(得分:5)
因为result
是一个被声明为调用s1
函数的结果的函数。调用s1
返回s12
函数,该函数使用一个名为count
的变量,该变量在比自身更高的级别(范围)声明(这称为“自由变量”)。 / p>
如果在一个函数内部使用了一个自由变量,该函数的生命周期比声明自由变量的函数长,那么围绕该自由变量创建一个 "closure" 即使在终止声明的函数之后,它仍然在范围内。
第一次调用result
时,count
会增加1,并且该值会保留在内存中,这样当您第二次调用它时,您正在使用最后一个值。
答案 1 :(得分:5)
要理解这种行为,您需要真正了解闭包的作用。简短(但如果你真的与闭包无关,可能会让人感到困惑)答案是这样的:
每次s1
的调用都会执行以下操作:
A)创建一个名为count的变量并将其初始化为0
这似乎很简单......
B)创建一个从(A)增加变量的函数,并将addCount
变量设置为指向它
这里隐藏了一些重要的细节。此函数将更新的变量是在{strong> s1
的相同调用的步骤(A)中创建的变量。这是闭包机制的结果。< / p>
当s1
的第二次调用到达此步骤时,它会覆盖addEvent
的值,替换增加先前调用{{1}创建的count
的函数。使用新函数增加当前s1
调用创建的count
。
C)创建并返回一个记录在(A)中创建的变量值的函数
与(B)一样,此函数也会看到当前调用s1
的步骤A 创建的变量。
那是什么意思?
好吧,你调用s1
一次,它会创建一个值为0的变量,并返回一个记录该变量的函数(你将这个函数存储为s1
)。
作为一个副作用,该调用已将result1
设置为一个函数,如果您调用它,它将更改addCount
记录的变量的值...但是您不会调用它
而是再次调用result1
,用一个更新新变量(也初始化为0)的新函数替换s1
。它返回一个记录这个新变量的函数,您将其存储为addCount
。
现在通过result2
拨打电话,调用第二个函数更新第二个变量。然后调用addCount
记录第一个变量(从未更新过),然后调用result1
记录第二个变量(你增加一次)。
答案 2 :(得分:1)
因为变量addCount
具有全局范围。
答案 3 :(得分:0)
当运行函数s1
两次时,会生成两个名为count的变量,每个变量都在当前方法调用的范围内。
除此之外,您的addCount
方法对于两个调用都是全局的。你的第二个电话会覆盖第一个电话。
因此,在新的addCount
方法中,您可以进行第二次s1
调用。
因此,您对addCount
的调用在范围内有第二个count
变量并递增此变量。
打印结果时,您将返回两个范围,并在第一个电话的范围内获得count = 0
的正确值,并在第二个范围内获得count = 1
。