为什么需要在这个闭包中创建一个变量

时间:2015-02-03 17:05:31

标签: javascript function variables closures

您好我有以下关闭

    function createCounter() {
       var numberOfCalls = 0;
       return function() {
          return ++numberOfCalls;
       }
    }

 var fn = createCounter();
fn()
fn()

我相信我理解范围以及内部函数在外部函数返回后保留外部函数值的事实。

我不明白为什么我需要创建这个变量

var fn = createCounter()

然后调用变量fn()而不是最初调用createCounter()

我看到createCounter()只返回' function()'而不是必须是什么' 1'我不明白为什么。

感谢您的帮助。阅读许多教程仍然有理解这一点的问题。

请注意:问题不在于如何使代码更有说服力或更好,而是在于了解已经完成的工作

2 个答案:

答案 0 :(得分:0)

当调用createCounter时,它返回另一个函数,除非你这样做,否则不会评估返回的函数。请记住,JavaScript函数也是对象。它们可以是函数的返回值。

所以当你这样做时:

var fn = createCounter();

fn仅引用createCounter函数返回的函数,而不引用其评估值。

如果您需要评估createCounter返回的函数,请尝试以下方法:

createCounter()();

这会评估返回的函数。

如果您这样称呼它,每次拨打numberOfCalls时,它始终会返回与创建新createCounter变量时相同的值。

答案 1 :(得分:0)

在Javascript中,函数是可以传递给其他函数并由其他函数返回的对象,如任何其他对象(例如字符串,数字......)。

这样做:

function foo(arg) { /* ... */ }
var someObject = new String("Hello");
foo(someObject);

类似于:

function foo(arg) { /* ... */ }
var someFunction = new Function("Hello", "...");
foo(someFunction);

因此,函数可以返回另一个函数,可以根据需要调用该函数。

function foo() {
   return new Function(...);
}
var functionReturnedByCallingFoo = foo();
functionReturnedByCallingFoo(); // can be invoked
functionReturnedByCallingFoo(); // and again
functionReturnedByCallingFoo(); // and again

现在,函数几乎从不使用Function构造函数声明,而是使用名为“函数声明”或“函数表达式”的结构声明 - 基本上,我们在前面的示例中使用函数定义函数“foo”的方式签名和由大括号分隔的函数体。

在这种情况下,函数体内部的语句可以读取和写入在函数本身之外声明的变量(“自由变量”),而不仅仅是根据词法作用域规则在函数内声明的变量。这就是我们所说的闭包。

因此,在您的情况下,createCounter()函数在被调用时定义了一个名为“numberOfCalls”的局部变量,然后返回一个函数 - 该函数的主体可以访问该变量。执行返回的函数会在每次调用时更改变量的值,就像对任何“全局”变量(即在外部作用域中声明的变量)一样。

多次执行createCounter()函数只需每次重新创建一个新的局部变量“numberOfCalls”,将其初始化为零,并返回一个可以访问该变量的新函数对象。