什么是闭包?
什么是闭包?
- 说明
- 闭包
有些读者可能很好奇,为什么闭包会成为一个独立的概念,以及为什么它需要编程语言提供额外的支持。这些疑惑可以本文中找到答案。
说明
函数是编程语言中比较基本的概念。但随着技术的发展,函数的功能被延伸,一些类似函数但又与之有别的概念诞生,如 lambda 表达式、箭头函数等等。但为了便于描述,本文也将它们称为函数,尽管普通的函数与它们不尽相同。
闭包的概念在 JavaScript 中更常用,后来也延伸到 Java、C++ 中。
闭包
首先,闭包(closure)指一个函数。
简单地说,闭包是使用了它的外部函数局部变量的函数。
具体来讲,如果 A 是一个函数,而 B 是在 A 中定义的一个函数(表达式),且在 B 的函数体中(不包括“在调用函数 B 时,在 B 的形参中”)使用了 A 的局部变量 a,那么就将函数 B 称为闭包。
闭包 B 之所以与普通的函数有所不同,因为它将导致它所使用的外部函数的变量 a,不会在该外部函数 A 执行完时销毁。而之所以会这样,是因为如果在刚才的 A 中,将函数 B(不是 B 的返回值)传给其它不在 A 包含范围内的函数 C,那么当 A 执行完时,函数 C 想使用这个函数 B,那么将必须保证B使用的变量 a 一直存在。这并不能通过判断变量 a 是否被引用来保证变量 a 是否可以销毁。其中的缘由略复杂,这里将情景详述如下:
【1】A 是一个函数,B 是在 A 中定义的一个函数(表达式),且在 B 的函数体中使用了 A 的局部变量 a。函数 C 是一个与 A 没有包含关系的函数,且 A 与 C 之间不存在互相调用。
【2】A 将 B 传给了一个不在 A 包含范围内的公共存储区 R。
【3】函数 A 执行完毕,此时函数 C 还没有开始执行。
【4】程序去执行与函数 A、B、C 均无关的代码。
【5】函数 C 开始执行,从公共存储区R取出并调用了函数 B,B 使用了 A 的局部变量 a。
可以看出在过程【4】中,A 的局部变量 a 没有被任何代码块所引用,因为此时函数 A、B、C 都没有执行,没有执行就意味着函数 A、B、C 中任何局部变量都不会创建,因此 A 的局部变量 a 在过程【4】中是不会被引用的。按一般的变量回收规则,a 理应被销毁,但这将导致过程【5】引发异常。因此,一个编程语言要支持闭包,就要使用一个额外的机制来防止过程【3】与【5】之间的局部变量 a 不会被回收。
还没有评论,来说两句吧...