初探闭包

一、什么是闭包?

闭包是能访问其他函数作用域的函数。
分析一下这句话就是:
1、闭包是一个函数;
2、闭包不仅能访问自己的作用域,还可以访问其他函数的作用域。

二、怎么创建闭包?

只要在一个函数中再定义一个函数,这个内部函数就是闭包。
注意:只要满足一个函数在另一个函数的内部的条件,这个内部函数就是闭包,不管这个内部函数是以怎样的形式存在于外层函数中的。下面举几个例子:
形式一:
function father () {    
    function son () {
    }
}
形式二: 
function father () {   
    var object = new Object();    
    object.son = function () { 
   }
}
形式三: 
function father () {   
    var object = {       
    son : function(){
     }   
  };
}
以上三种形式定义的内部函数都是闭包。
  • 形式一:在一个函数中又定义了个函数,这完全符合闭包的定义,不用多说。
  • 形式二:在一个函数中先创建了一个对象,然后在对象内部定义了函数,这也是闭包。
  • 形式三:本质上和形式二一样,也是先在函数内部定义了一个对象,再在对象内部定义了个闭包。只不过定义对象的方式和形式二有所区别。

三、闭包的原理

上一篇讲了作用域链和执行环境,一般来讲,当函数执行完毕后,其执行环境就会从执行环境栈弹出,变量对象也会被销毁,内存中仅保存全局作用域。但是,闭包不是这样子的:   
var name = "The window";//全局变量
function myObject () {        
    var name = "my Object";        
    return function () {            
      return name;       
  }    
 }    
var result = myObject();//result就是那个匿名函数    
result();//"my Object"//访问到了myObject()的局部变量name
当匿名函数从myObject()中被返回时,它的作用域链初始化为包含其自身变量对象、myObject()变量对象和全局变量对象。这样匿名函数就可以访问myObject()和全局环境中的定义的变量。最关键的是,myObject()函数执行完毕后,其变量对象也不会被销毁,因为匿名函数的作用域链仍然引用着这个活动对象。也就是说,虽然myObject()函数return之后,它执行环境弹出了执行环境栈,作用域链被销毁,但是它的变量对象仍然在内存中,直到匿名函数被销毁。
综上所述,闭包之所以能访问其外层函数作用域中的变量,是因为闭包的作用域链中存在外层函数的变量对象。即使外层函数执行结束,但由于其变量对象仍然被内层函数的作用域引用,因此不会被内存回收,直到闭包执行结束后,外层函数的变量对象才会被回收。

四、闭包的常考题

若闭包在外层函数执行结束后执行,那么它只能获取到外层函数中所有变量的最终状态。
  • 例1:   
function father(){   
    var array = [];    
    for (var i=0; i<10; i++) {       
    array[i] = function(){           
      return i;       
     }    
 }    
return array;
}
father函数执行后会返回一个包含闭包的数组,每个闭包都会返回i。 
由于这里的闭包调用时,外层函数早就执行结束了,外层函数变量对象中i值已经变成了9,此时不管执行array中的哪个闭包,返回的结果都是9。 
但是,如果在闭包外层函数执行过程中立即执行闭包,那么结果就不一样了,请看例2.
  • 例2:
function father(){    
    var array = [];    
    for (var i=0; i<10; i++) {       
      array[i] = (function(){           
      return i;        
    })();    
}    
return array;
}
此时的闭包在外层函数执行时就立即执行,在那个时刻,闭包中i的值就是外层函数当前i的值,因此返回的array中存储的将是0-9。

参考:https://blog.csdn.net/u010425776/article/details/53709111

           https://blog.csdn.net/xiaozhuxmen/article/details/52281301

再次感谢各位大牛的技术分享,受益匪浅!如有理解不对的地方,还望各位博友多多指点~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值