JavaScript 带闭包和 IIFE 的计数器

JavaScript counter with closure and IIFE

在 www.w3schools.com/js/js_function_closures.asp 上有一个闭包中计数器的基本示例,据我所知,这是一个 IIFE:

var add = (function () {
    var counter = 0;
    console.log(counter);
    return function () {return counter += 1;}
})();

add();
add();
add();

// the counter is now 3 

然而,在对范围、闭包和 IIFE 进行了数小时的阅读(不是第一次)并查看了其他简单示例之后,我仍然不明白为什么 var counter = 0; 行只执行一次。我在该行之后添加的控制台日志从不输出任何内容,就好像它从未被调用过一样。

为什么每次调用 add() 时计数器都不会重置为 0?我理解错了什么概念?谢谢你的帮助。

I still don't understand why the var counter = 0; line is only executed once.

因为IIFE函数只调用了一次。 add() 调用执行此函数:

function () {return counter += 1;}

这是从 IIFE 返回的。您可以通过提供函数名称并检查正在执行的函数的名称来检查:

var add = (function iife() {
    var counter = 0;
    console.log(counter);
    return function inner() {return counter += 1;}
})();

add.name; // `inner`, not `iife`

The console log I added right after that line never outputs anything, as if it never gets called

不可能。它应该只输出一次 0

Javascript 引擎的第一步(在声明 add 之后)是初始化 add,这会导致调用 IIFE,这会再次导致:

var add = function () {

    return counter = counter++
}

因为IIFEreturns这个函数作为值要赋值给add。分配给 add 的函数仍然可以访问 IIFE (var counter) 的词法范围:即闭包。

每个 add() 都是对从 IIFE 返回的函数的调用,因此 var counter = 0 只被调用一次(在初始化 add 时)。