闭包,能吃么

最近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;

取消对闭包引用,进而取消闭包所引用的它的外部作用域的变量,达到让垃圾回收车主动回收掉不再使用的内存的目的。节约空间呗~