JavaScript/闭包
外观
闭包是一种技术,其中函数与其周围变量(词法环境)捆绑在一起(封装)。 通常,闭包是在像 JavaScript 这样的函数式编程语言中实现的,它们支持柯里化。
首先,我们展示函数对其词法环境的访问。 仅此而已不是一个闭包。
"use strict";
function incrementByCertainValue(param) {
return param + certainValue;
}
let certainValue = 10;
alert(incrementByCertainValue(8)); // 18
certainValue = 100;
alert(incrementByCertainValue(8)); // 108
函数incrementByCertainValue
将其参数增加certainValue
变量的值。 因为incrementByCertainValue
以及certainValue
是在同一个块内定义的,所以函数可以访问该变量。 每当调用该函数时,它都会读取该变量并使用它来计算其返回值。
为了将上面的例子扩展到闭包,我们必须将一个(内部)函数与访问其词法环境的变量(通常是另一个函数)结合起来,并且通过返回这个内部函数来保存这种状态。
"use strict";
function incrementByCertainValue(param) {
// declare a function that will perform the work. (Only declaration, currently not invoked.)
const add = function (certainValue) {
// access to 'param' from lexical environment and to its parameter 'certainValue'
return param + certainValue;
}
return add;
}
const incrementByFive = incrementByCertainValue(5);
alert(incrementByFive(8)); // 13
const incrementBySix = incrementByCertainValue(6);
alert(incrementBySix(8)); // 14
alert(incrementByFive(10)); // 15
(外部)函数incrementByCertainValue
- 包含一个参数
param
, - 定义一个(内部)函数
add
,它接受另一个参数certainValue
, - 除了其参数之外,(内部)函数还可以访问其词法环境,其中定义了
param
- 返回(内部)函数。
到目前为止,只有声明,没有运行代码。
当变量incrementByFive
在第 12 行声明时,它被初始化为函数incrementByCertainValue(5)
的返回值。 这是关键点代码运行和闭包技术起作用的地方。 在incrementByCertainValue
中,5 被称为参数/变量param
。 接下来,函数add
使用来自其词法环境的param
创建。 此函数add
接受一个参数,该参数必须稍后从调用例程中提供。 incrementByCertainValue
的返回语句提供此函数add
,该函数已将值“5”绑定到其主体中。 请注意,函数名称add
是任意的,在incrementByCertainValue
之外看不到。
当incrementByCertainValue
第二次使用参数“6”调用时,“6”将绑定到一个单独的第二个函数。