JavaScript闭包问题:为什么第二次调用outerFn会创建一个新的outerVar实例?

JavaScript Closure question: why is the second call to outerFn creating a new instance of outerVar?

本文关键字:一个 实例 outerVar 创建 问题 闭包 为什么 第二次 outerFn 调用 JavaScript      更新时间:2023-09-26

我有一个JavaScript问题。让我引自《学习jQuery》一书,第389-390页。这个问题与闭包有关。

我不明白为什么第二次调用outerFn()不是重置outerVar的值,而是[是],而是创建一个新的outerVar实例,绑定到第二个函数调用的范围。

JavaScript是怎么做到的?关于JavaScript,我需要知道些什么才能自己推断出来?

电子邮件的其余部分是书中的引文。

function outerFn() {
  var outerVar = 0;
  function innerFn() {
    outerVar++;
    $('#example-7').print('outerVar = ' + outerVar);
  }
  return innerFn;
}
var fnRef = outerFn();
fnRef();
fnRef();
var fnRef2 = outerFn();
fnRef2();
fnRef2();

现在我们的函数调用有了更有趣的行为:outerVar = 1outerVar = 2outerVar = 1outerVar = 2我们得到了前两种效果的混合。对innerFn()的调用独立引用自增outerVar。注意,第二次调用outerFn()不是重置outerVar的值,而是创建一个新的outerVar的实例,绑定到第二个函数调用的作用域。的这样做的结果是,在上述调用之后,对fnRef()的另一个调用将输出值3,随后调用fnRef2()也会输出3。的两个计数器是完全分开的。

这就是闭包的全部思想。正如上述wiki链接的第一段所述:

在计算机科学中,闭包(也称为词法闭包、函数闭包或函数值)是一个函数以及该函数的非局部名称(自由变量)的引用环境。这样的函数被称为"封闭"其自由变量。引用环境在创建闭包时将非局部名称绑定到作用域中相应的变量,另外将它们的生命周期延长到至少与闭包本身的生命周期一样长。

这种行为并不是javascript特有的——在所有提供闭包支持的语言中都会发生这种情况

你可能想多了。

与往常一样,每次调用outerFn时,它都会为该函数的特定调用创建一个新的outerVar变量——这是它的局部作用域的一部分。因此,返回(或以某种方式传递)的特定outerFn调用范围内的任何函数将继续访问该范围-闭包。

如果没有闭包,函数将被限制使用作为参数传递的变量。

为了能够使用在函数外部声明的变量,必须在创建函数时捕获这些变量。每次创建函数时,它都会捕获当前范围内的完整变量集。

outerVar只是函数outerFn中的一个局部变量。每次调用outerFn都会创建一组特定于该特定函数调用的新的局部变量。

如果你想让outerVar从一次调用到另一次调用都保留它的值,那么你需要在函数调用之间存在的outerFn之外的作用域中定义它(它可以是全局作用域,也可以是存在于函数级别之上的其他作用域)。