《JavaScript ES6 函数式编程入门经典》 4.1了解闭包。简单地说,闭包是内部函数。

那么什么是内部函数呢?它是在另一个函数内部的函数。比如:

function outer() {
function inner() {
// body...
}
}

这就是闭包,函数inner称为闭包函数。闭包函数如此强大的原因在于它对作用域链的访问。


《JavaScript高级程序设计(第3版) [Professional JavaScript for Web Developers 3rd Edition] 》

7.2 闭包

有不少开发人员总是搞不清匿名函数和闭包这两个概念,因此经常混用。闭包是指有权访问另一个函数作用域的函数。创建闭包的常见方式,就是在一个函数内,创建另一个函数。


《代码之髓 编程语言核心概念》

代码这髓 第11章 对象与类 11.5

什么是闭包

说到闭包( closure)这个概念,想必很多人一时也说不出究竟何为闭包。它是创建具有对象性质的事物的一种技术。

很多语言都支持定义带有某种状态的函数。比如,可以定义像计数器一样每调用一次显示的数字加1的函数。我们用 JavaScript语言来实现一下。

function makeCounter(){
var count = 0
function push(){
count++;
console. log(count);
}
return push;
}

c = makeCounter()

c() // -> 1
c() // -> 2
c() // -> 3

这段代码中,函数 makeCounter中定义了变量 count和函数push,并返回函数push。然后,通过调用函数 makeCounter将返回值赋给变量c,然后调用它三次。每调用一次,显示的值就加1.这是怎么做到的呢?函数 make Counter首先创建了一张名字和值的对照表,把变量 count的值设为0.然后定义了函数push,并将其返回。函数push将其被定义时的对照表一同带出 makeCounter函数。随后,每当被调用时,函数push在被定义时的对照表的值就加1。

事实上,并没有所谓闭包的特殊的语法结构。如果有一种语言,它可以在函数中定义函数,有允许嵌套的静态作用域,并且可以把函数作为返回值传递给变量,那么它只要通过函数的嵌套就可以实现带有某种状态的函数

为什么叫做闭包

看到闭包这个名字,总有一种什么东西被严实地包裹起来了的感觉。为什么会叫做闭包呢?某 Standard ML的教材上做了如下解释。

为什么把这称为闭包?一个包含了自由变量的开放表达式,它和该自由变量的约束环境组合在一起后,实现了一种封闭的状态。

—- Ake Wikstrom, Functional programming using standard ML, Prentice-Hall, 1987.

拿上面一段代码来讲,函数push使用了变量 count,然而该变量并不是在函数push中定义的。这种变量被称为自由变量。函数push就是一个包含了自由变量的开放函数。而函数 makeCounter的对照表中为0的值和为 count的名字结合在了一起。这种给值绑定一个名字的操作叫做(名字)约束。

这样开放函数push和 makeCounter的对照表组合配套之后,无需在这以外的作用域中寻找变量的定义,从而达到了某种完备的状态。通过这样表现出一种封闭的属性。

相关推荐