1

我目前正在完成有关 JavaScript 的阅读。我在http://www.w3schools.com/js/js_function_closures.asp上关于 JavaScript 中的闭包(允许“私有变量”)的章节。

这个例子是一个计数器:

<!DOCTYPE html>
<html>
<body>

<p>Counting with a local variable.</p>

<button type="button" onclick="myFunction()">Count!</button>

<p id="demo">0</p>

<script>
var add = (function () {
    var counter = 0;
    return function () {return counter += 1}
})()

function myFunction(){
    document.getElementById("demo").innerHTML = add();
}
</script>

</body>
</html>

它声明它使用自调用函数将计数器设置为 0一次,并且每次 add() 迭代时计数器加一。但是,我在代码中看到用于自调用函数的花括号围绕在counter = 0和递增计数器的函数周围。我很难想象这两个命令到底是如何在自调用函数中出现的,但是一个只运行一次,而另一个在每次迭代时都运行。

4

1 回答 1

9

让我们把这个问题分解成几部分:

(1)

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

第一部分是自调用匿名函数,这意味着add将接收该函数的执行结果。在这种情况下,它只不过是以下匿名函数:

function () {return counter += 1;}   (2)

所以这意味着 add 将是一个函数!

现在有趣的是,在 siaf (1)(自调用匿名函数)内部,我们声明了一个计数器变量,初始化为零:

var counter = 0;

因为 counter 属于 (2) 的外部范围,所以 (2) 可以访问它!

JavaScript 所说的是,一个函数在创建时将捕获其环境并将其持久化,因此闭包(关闭)只不过是函数及其创建环境的组合。这意味着在 return 语句之后,现在将持有对 (2) 的引用的 add 函数仍然可以访问最初设置为 0 的 counter 变量;

所以要递增计数器,我们需要递增 (2),这意味着递增 add 像这样:

add();

ps:使用 Function 构造函数创建并以与(2)相同的方式返回的函数不会捕获计数器变量!

于 2014-06-17T21:03:56.483 回答