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

why does a variable need to be created in this closure

嗨,我有以下闭包

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

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

而且我相信我了解作用域以及内部函数在外部函数返回后保留外部函数值的事实。

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

var fn = createCounter()

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

我看到 createCounter() 只是 returns 'function()' 而不是必须为“1”的内容,我不明白为什么。

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

请注意:问题不是关于如何使代码更多 eloquent 或更好,而是关于对所做工作的理解

当调用 createCounter 时,它 return 是另一个函数,除非您这样做,否则不会计算 returned 函数。请记住,在 JavaScript 中函数也是对象。它们可以是函数的 return 值。

所以当你这样做时:

var fn = createCounter();

fn 仅引用由 createCounter 函数 return 编辑的函数,而不是其计算值。

如果您需要评估由 createCounter 编辑的 return 函数,请尝试类似的操作:

createCounter()();

这会评估 returned 函数。

如果你这样调用它,它总是 return 相同的值,因为它会在你每次调用 createCounter.

时创建一个新的 numberOfCalls 变量

在 Javascript 中,函数是可以传递给其他函数并由其他函数 return 编辑的对象,就像任何其他对象(例如字符串、数字...)一样。

这样做:

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

类似于:

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

一个函数因此可以 return 另一个函数,可以根据需要调用它。

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

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

在这种情况下,函数体内的语句可以读取和写入在函数本身之外声明的变量 ("free variables"),而不仅仅是在函数内声明的变量,按照词法规则范围。这就是我们所说的闭包。

因此,在您的情况下,createCounter() 函数在调用时定义了一个名为 "numberOfCalls" 的局部变量,然后是 return 一个函数 - 其主体可以访问该变量。执行 returned 函数会在每次调用时更改变量的值,就像对任何 "global" 变量(即在外部范围中声明的变量)一样。

多次执行 createCounter() 函数只会每次重新创建一个新的局部变量 "numberOfCalls",将其初始化为零,然后 return 一个可以访问该变量的新函数对象.