闭包,能吃么
最近simona在面试,一面动不动就问闭包,这个包子啊,好吃么?哈哈,其实吧,很多时候程序员一直用着闭包,也知道有这么回事儿,可是有时候用语言去表达也是醉醉的。。。。所以,叙述不出来没事儿,也不代表能力,抽个空,总结一下也就完事儿了,是吧?so,让我们来吃掉这个包子~
好的,开始认知:
- 是什么
闭包是指有权访问另一个函数作用域中的变量的函数(红宝书如是说)
- 怎么创建
在一个函数内部创建另一函数 (红宝书如是说)
- 有什么用
函数执行完后,让函数的内部变量不被当做垃圾收回的一种手段 (我自己如是瞎说哈哈)
好了,就这么些东西,好像不是很好吃啊,干巴巴的。。。那我们就深入一些,把包子馅给吃掉吧~
######函数执行发生了什么? 看了一下红包书,说了很多东西,其实我们可以更感性的理解一下。说一下我的理解:
- 函数就是程序执行的一个提前写好的计划清单:plan
- 要开始做这个计划就需要在plan上写上我的计划需要的东西,例如我们要计算今天的花费:
- 早餐=5元
- 中餐=15元
- 晚餐=借的别人的钱
- 由于我要借别人的钱,所以别人的plan要先执行,我才能借
- 但是plan执行有个规则,就是plan执行完之后会把执行的内容所要求准备的钱都清空,为什么呢?钱都花了,当然没了呗。。。如果再执行这个plan就得再准备新的钱了
- 好了,我们来开始这个执行过程:
- A的 plan:早餐=5元;中餐=10元;晚餐=15元;可借别人的钱=10元;
- B的 plan:早餐=5元;中餐=15元;晚餐=A可以借的钱
- 情况1:A plan执行完,A吃饱了,然后A中所有准别的钱都清空了, 然后B plan再执行,发现晚餐的钱被清空了。。。。。哭。。。晚上只能饿肚子了。。
- 情况2:A plan执行完,A吃饱了,然后正当A中所有的钱要被清空的时候,B说等等,让我先拿到你借我的钱你再清空,然后B执行的时候就拿到了A可以借的钱。
这翻译成程序就是:
// 情况1
function Aplan() {
var 早餐=5;
var 中餐=10;
var 晚餐=15;
var 借钱=10;
}
function Bplan() {
var 早餐=5;
var 中餐=15;
var 晚餐=借钱;
}
Aplan();
Bplan();
Aplan和Bplan现在各自独立,所以B的晚餐是找不到的。
// 情况2
function Aplan() {
var 早餐=5;
var 中餐=10;
var 晚餐=15;
var 借钱=10;
function Bplan() {
var 早餐=5;
var 中餐=15;
var 晚餐=借钱;
}
Bplan();
}
Aplan();
这次能借到钱了。。。执行完后A和B的plan的钱也就清空了。但是我们如果有这么个需求,就是凭什么A来决定整个计划的实施时间啊,A花钱的时候B并不想花钱啊。。。可是B想借A的钱啊,可是A花完钱就不管不顾的把准备借B的钱也清空了啊。。。怎么办呢?
没错,利用闭包来达到这个目的。
// B的命运自己掌握
function Aplan() {
var 早餐=5;
var 中餐=10;
var 晚餐=15;
var 借钱=10;
return function Bplan() {
var 早餐=5;
var 中餐=15;
var 晚餐=借钱;
}
}
var Bplan = Aplan();
// 好了,B想什么时候执行都行
Bplan();
为什么这个B可以拿到钱了呢,A执行完不是清空了么,是的,A执行完的时候清空了早中晚餐的钱,然后又想清空借的钱,可是它发现你妹的B已经把钱借走了啊,那好吧,钱放在那里等B执行完的时候再清空吧。
简单来说,就是B函数引用了A函数的变量。这个例子可能不太好,但是简单说明了闭包是什么,就是例子中的Bplan啊哈哈。
再学术的总结一下,闭包是指有权访问另一个函数作用域中的变量的函数。利用闭包的特点,我们可以让闭包持有外部作用域的变量而不释放,到达组织垃圾回收或者延迟垃圾回收的目的。所以呢情况2下最好最后加一句:
Bplan = null;
取消对闭包引用,进而取消闭包所引用的它的外部作用域的变量,达到让垃圾回收车主动回收掉不再使用的内存的目的。节约空间呗~