为什么这段代码有两个不同的结果?

时间:2017-02-21 16:23:42

标签: javascript

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

4 个答案:

答案 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