JavaScript编程精解(原书第3版)
上QQ阅读APP看书,第一时间看更新

3.8 闭包

将函数视为值的能力,以及每次调用函数时都重新创建(函数中的)局部绑定的事实,都会带来一个有趣的问题。当创建它们的函数调用不再处于活动状态时,局部绑定会发生什么?

以下代码显示了此示例。它定义了一个函数wrapValue,它创建了一个局部绑定。然后它返回一个访问并返回此局部绑定的函数。

这是允许的,并且可以按照你的预想工作——仍然可以访问绑定的两个实例。这种情况很好地证明了每次调用都会重新创建局部绑定的事实,并且不同的调用不能在其他调用的局部绑定上进行操作。

这个能够引用封闭作用域中局部绑定的特定实例的功能被称为闭包(closure)。引用其周围局部作用域的绑定的一个函数称为一个闭包。这种行为不仅使你不必担心绑定的生命周期,而且还能以某种创造性的方式使用函数值。

稍作修改,我们可以将前面的示例转换为能够创建乘以任意数量的函数。

由于参数本身就是局部绑定,因此实际上不需要来自wrapValue示例的显式local绑定。

考虑这样的程序需要做一些练习。一个好的思路模型是将函数值视为同时包含其函数体内的代码和创建它们的环境。调用时,函数体会看到创建它的环境,而不是调用它的环境。

在此示例中,调用multiplier并创建一个将其factor参数定为2的环境。它返回的函数值(存储在twice中)会记住此环境。因此,当调用twice时,它将其参数乘以2。