闭包的理解
看到知乎的一个回答,觉得非常不错,抄下来备份记录
引用自知乎用户回答:
链接:https://www.zhihu.com/question/21865351/answer/2142927643
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
简单。
如果函数传入的不是全局变量,而是一个生命周期比这个函数还短的局部变量,怎么保证这个函数正常运行完。
一般的做法就是随着这个函数一起保存一个副本嘛。当然各个语言都有自己的做法。还有的语言根本就不支持闭包,函数运行着的时候,变量没有了,销毁了。那就报错呗
-------------------看上面就够了,下面是一些私货,可看可不看---------------
扩展一下:闭包的概念来自抽象代数,指的是能让一个运算闭合的集合。我们编程定义的函数,也是一种运算,如果变量来自外部,那这个运算对于这个函数的环境来说是不闭合的,因为除了函数的环境,还依赖变量的环境。所以我们要在函数的运行的时候,保证运算是闭合的,不管是通过复制变量副本,还是操作指针,还是别的什么办法,这一系列操作,就是闭包。
再次扩展一下:关于闭合
闭合这个数学概念我觉得很妙。定义不难理解:
封闭性,即闭包(数学)。数学中,若对某个集合的成员进行一种运算,生成的仍然是这个集合的成员,则该集合被称为在这个运算下闭合。
举个简单的例子,减法对于正整数是不闭合的,除法对于整数是不闭合的,开根号对于有理数是不闭合的。如果计算不闭合,就会出现bug,譬如整数的除法出现小数。对于人类来说,这种bug可能会开辟全新的数学领域(人类数学就是这么发展的),但是对于计算机来说,就是报错、死机。
闭包的概念,不仅仅是用于保证每一个函数能够顺利运行,还可以被用于计算机语言设计。譬如c#语言的设计就是闭合思维的典范。C#的类库设计对于低级的、初级的功能闭合,用c#实现较为简单的功能基本学一两个小时就可以做出不错的程序。但如果想用到高级的功能,就必须突破这层闭合,学习使用成本都较高,减少了新手犯错的几率,又保留了高手的自由度。再譬如,c++指针为何难用,就是因为指针的运算规则完全游离于程序规则,在任何情况下都提供了不闭合的可能性。所以出bug不要太容易。
此外,吐槽一下。编程中的闭包是给面向对象擦屁股的。因为对于值传递的编程语言(c语言之类的)根本不存在计算不封闭的问题,变量传递都是内存直接复制。
根源上,图灵机式的顺序编程对于值传递来说是闭合的,但是对于大量的引用传递其实一开始就是不闭合的。所以只要有引用类型的语言,必须要给这种不闭合擦屁股,想办法处理变量和函数生命周期不一致的问题。这是面向对象的原罪。