今天在写代码之余看了下js闭包,相对于以前的理解又有了稍微深刻点的理解。在此分享下个人理解:数据库
本文总共分为五个大的部分:1.理解js闭包前须要理解的js其余慨念。2.js闭包的特性。3.闭包举例。4.使用js闭包的好处。5.js闭包的用途。6.优化个人js代码。json
js做用域链:做用域链是js函数在建立的时候定义的,用于寻找到变量的一个索引。做用域链索引的内部规则是将函数自身的本地变量放在最前面,把自身的父级函数变量放在其次,再把高一级的函数的变量放在更后面,以此类推知道全局对象为止。当须要查找一个变量时,js解释器会从做用域链去查找该变量,先从该函数的本地变量开始查找,若是没有,则在下一级做用域链进行查找,若是查找到相应变量则返回该变量,若是直到最后也没找到相应变量则返回undefined。缓存
js的内存回收机制:一个函数在执行开始的时候,会给其中定义的变量划份内存空间保存,以备后面的语句所用,等到函数执行完毕返回了,这些变量就被认为是无用的了,对应的空间也就被回收了。下次再执行此函数的时候,全部的变量又回到最初的状态,从新赋值使用。可是若是这个函数内部又嵌套了另外一个函数(这就是闭包了),而这个函数是有可能在外部被调用到的。而且这个内部函数又使用了外部函数的某些变量的话.这种内存回收机制就会出现问题。若是在外部函数返回后,又直接调用了内部函数,那么内部函数就没法读取到他所须要的外部函数中变量的值了。因此js解释器在遇到函数定义的时候会自动把函数和他可能使用的变量(包括本地变量和父级和祖先级函数的变量(自由变量))一块儿保存起来。也就是构建一个闭包,这些变量将不会被内存回收器所回收,只有当内部的函数不可能被调用之后(例如被删除了,或者没有了指针),才会销毁这个闭包,而没有任何一个闭包引用的变量才会被下一次内存回收启动时所回收。闭包
a:闭包的外层是个函数,闭包内部有函数。函数
b:闭包会return内部函数,闭包返回的函数内部不能有return。(若是有会结束闭包)优化
c:执行闭包后,闭包的内部变量会存在,闭包内部函数的内部变量会回收。spa
1 function outerFun(){ 2 var myVal=0; 3 function innerFun(){ 4 alert(++myVal); 5 } 6 return innerFun; 7 } 8 var myFun = outerFun(); 9 myFun();myFun();
此js代码在执行的过程当中分别alert出1,2。由此可知执行闭包后,闭包的内部变量会存在,闭包内部函数的内部变量会回收。指针
使用闭包有如下几大好处:code
a:但愿一个变量长期驻扎在内存中。对象
b:避免全局变量的污染。
var abc = (function(){ //abc为外部匿名函数的返回值 var a = 1; return function(){ a++; alert(a); } })(); abc(); //2 ;调用一次abc函数,实际上是调用里面内部函数的返回值 abc(); //3
c:私有成员的存在。
var aaa = (function(){ var a = 1; function bbb(){ a++; alert(a); } function ccc(){ a++; alert(a); } return { b:bbb, //json结构 c:ccc } })(); aaa.b(); //2 aaa.c() //3
a:匿名自执行函数。
(function(){ alert("已进入就执行"); })();
咱们建立了一个匿名的函数,并当即执行它,因为外部没法引用它内部的变量,所以在执行完后很快就会被释放,关键是这种机制不会污染全局对象。
b:使用闭包对数据进行缓存。
在咱们作项目的时候,常常遇到一些数据很是大且没有必要进行及时查询的数据。以下拉框数据等。那么在此时咱们能够在启动应用的时候在页面将这些数据进行缓存起来,若是缓存中有咱们须要的数据则直接读缓存,若是缓存中没有咱们须要的数据,则进行查询数据库。闭包能够为咱们作到这点。
var CachedSearchData = (function () { var cacheData = [], count = cacheData.length; return { getSearchData: function (id) { if (id in cacheData) {//若是结果在缓存中 return cacheData[id];//直接返回缓存中的对象 } else { //到数据库中查找 alert("search in database"); } }, clearSearchData: function (id) { if (dsid in cache) { cache[dsid].clearSelection(); } } }; })(); CachedSearchData.getSearchData(77);
在之后的js代码中可以使用闭包进行优化一些代码。
var person = function(){ //变量做用域为函数内部,外部没法访问 var name = "default"; return { getName : function(){ return name; }, setName : function(newName){ name = newName; } } }(); alert(person.name);//直接访问,结果为undefined alert(person.getName()); person.setName("zhangsan"); alert(person.getName());