【问题标题】:Use of self-Invoking functions in JavaScript closures在 JavaScript 闭包中使用自调用函数
【发布时间】:2014-06-17 20:50:36
【问题描述】:

我目前正在完成有关 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 和递增计数器的函数。我很难想象这两个命令究竟是如何在自调用函数中的,但是一个只运行一次,而另一个在每次迭代时都运行。

【问题讨论】:

  • IIFE(立即调用函数表达式)的声明返回另一个函数。因此,IIFE 的初始运行创建了counter 变量并返回一个对counter 变量有效的函数。因此,当您调用 add() 时,您不是在运行 var counter = 0 代码,而是在运行 IIFE 的 return(恰好是一个函数)。
  • counter += 1 可以是++counter

标签: javascript self-invoking-function


【解决方案1】:

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

(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 说的是,函数在创建时会捕获其环境并将其持久化,因此闭包(close over)只不过是函数及其创建环境的组合。这意味着在 return 语句之后,现在将持有对 (2) 的引用的 add 函数仍然可以访问最初设置为 0 的计数器变量;

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

add();

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

【讨论】:

  • 忘掉“匿名函数”吧,它们都是function expressions,或者只是函数。
  • 它们是匿名函数 :)
  • 分配给变量的函数表达式是否比函数声明更“匿名”?
  • 我明白你的意思,通过指出规范,但相信我更喜欢称他们为匿名。我也可以用 C 风格说函数指针 :)
  • developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 函数表达式和函数语句的主要区别在于函数名,在函数表达式中可以省略函数名来创建[[[[匿名函数]]]]。
猜你喜欢
  • 1970-01-01
  • 2011-12-25
  • 2015-03-04
  • 2016-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-22
  • 1970-01-01
相关资源
最近更新 更多