这对 JavaScript 函数有何不同?

How is this pair of JavaScript functions different?

我很难辨别 JavaScript 闭包的工作原理。请看一下这两个函数,并说出它们的不同之处,即多次调用它们会产生完全不同的结果:

函数 1

var add = (function() {
  var counter = 0;
  return function() {
    return counter += 1;
  }
})();
console.log(add()); // result is 1
console.log(add()); // result is 2
console.log(add()); // result is 3

函数 2

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

您无法访问在该外壳之外的外壳内定义的任何变量。这有助于避免冲突,例如多个函数使用相同的变量名。

在情况 1 中,您正在 return 一个在外部 IIFE 上有一个 Closure 的函数。因此,returned 函数即使在 returned(即闭包)之后也能够存储 count 的值,因此每次调用 add()[= 时都会获得更新的值20=]

你的情况2似乎不正确。您没有定义 plus 函数。即使你定义了它,你也会得到 undefined,因为你没有 returning 来自 add()

的任何东西

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

当你returnplus()从它你只会得到1,因为你实际上是return每次执行counter += 1的结果每次 counter is reset to 0 当你调用 add()

在第一个示例中,声明了计数器,调用 add 时调用的函数本质上是:

function (){
    return counter += 1;
}

这很重要,因为不会在每次调用 add 时都重新声明 counter

在第二个示例中,每次调用 add 时都会重新声明 counter

How is this pair of JavaScript functions different?

在每个示例中,您都声明了两个函数,一个嵌套在另一个函数中。

在第一个示例中,您调用一次外部函数 ,return 内部函数并将其分配给 add。这意味着调用 add 只会 执行内部函数 .

在第二个例子中,add指的是外部函数。因此调用 add 将始终执行外部和内部函数。


如果我们稍微重写第一个示例(它仍然产生相同的结果),也许您会看到更好的区别:

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

var plus = add();
console.log(plus());
console.log(plus());

注意add只调用了一次,也就是说var counter = 0;只执行了一次,而plus才是我们真正调用的函数。因为 plus 是在 add 中定义的,它可以访问 counter.

在第一个示例中,外部函数是 运行 一次,它将计数器变量设置为零。外层函数returns内层函数,并将其赋值给变量add。当您调用 add() 时,内部函数 运行s 在其声明的上下文中,因此它可以递增计数器变量。

在第二个示例中,声明了名称为 add 的外部函数。每次调用 add 时,你 运行 这个外部函数。这个外部函数每次都将计数器设置为零,然后 运行 是内部 plus 函数,它将计数器递增到 1 并且 returns 它。

这是第一个片段中发生的事情。

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

在上面的语句中,您为变量 add 分配了一个增加 counter 的函数。

注意事项:

  1. 您可以通过执行封装函数来获得此函数。 (请注意什么是附件功能returns)

  2. 您可以通过在它后面放置 () 来执行封闭函数。

现在变量 add 是一个增加 counter 的函数。这里的环境设置为进行闭包 - 因此内部函数始终记住 counter.

的先前值

因此,每次通过 add 变量执行内部函数时,您都会看到增加的数字。