看了许多博客和教程大概理解了闭包的概念和大致作用,总结一下。
变量的作用域:
变量参考作用域区分,分为2种,全局变量和局部变量,全局变量什么时候都可以访问,除非将它销毁,但终究,使用全局变量是不好的,容易引起混乱,因为任何地方都可以用。但局部变量只有在函数内部可以访问,函数执行完毕后,该函数内部的局部变量被销毁,函数外部无法访问,比如:
function fn1(){ var age=23; } fn1(); alert(age); //报错
那么问题来了,我想使用函数内部的局部变量,怎么办呢,这里,就可以使用闭包:
function fn1(){ var age=23; function fn2(){ return age; } return fn2; } var num=fn1(); alert(num()); //23
以上代码,首先定义了一个fn1函数,函数内部定义了一个局部变量age并初始化,值为23,接下来定义了一个fn2函数,该函数内部将变量age返回,注意,这里是关键,因为fn2内部是可以访问到父函数的局部变量的,最后一步,将fn2函数返回。接下来,将fn1函数正式执行,并将返回值保存在变量num中,返回值也就是fn2整个函数,再将num执行并弹出,得到fn1的局部变量23。成功将该局部变量取出。
所谓闭包,这里,应该就是fn2这个函数。闭包将变量age一直保存在内存中,永远不会销毁。
这里,就有一个问题来了,闭包有啥用,这样也可以得到该局部变量呀,比如:
function fn1(){ var age=23; return age; } alert(fn1()); //23
但这里其实只是简单的将变量返回,并没有永远保存在内存中,执行完毕age还是销毁了,你再调用一次,只是重复的定义,返回。这里有个例子可以证明:
function fn1(){ var age=23; age++; return age; } alert(fn1()); //24 alert(fn1()); //24 alert(fn1()); //24
这里我想实现变量age累加,调用了3次函数,结果每次都是24,因为变量定义---返回---销毁。重复3次而已,但闭包可以实现:
function fn1(){ var age=23; function fn2(){ age++; return age; } return fn2; } var num=fn1(); alert(num()); //24 alert(num()); //25 alert(num()); //26
这里就很明了了,对比之下,变量age永远在内存中,"num()",就可以得到age,随时可以取用。
作用:
有啥用?2个作用:1、可以取得函数的局部变量。2、而且这些局部变量的值永远在内存中。
注意点:由于闭包会使变量一直存在,不会垃圾回收,内存消耗大。所以在明确不再需要时,及时销毁。比如:
function fn1(){ var age=23; function fn2(){ age++; return age; } return fn2; } var num=fn1(); alert(num()); //24 alert(num()); //25 alert(num()); //26 num=null; //销毁 alert(num()); //num is not a function
附加:使用闭包返回多个变量
如果想取用某个函数的数个局部变量怎么办呢,这里可以用数组或者对象的方法
数组的方法:
function fn(){ var name="张三", age=23; var arr=[function(){return name;},function(){return age;}]; return arr; } var item=fn(); var a=item[0](); //name var b=item[1](); //age console.log(a+"-----"+b); // 张三-----23
对象的方法:
function fn(){ var name="张三", age=23; var obj={ getName:function(){ return name; }, getAge:function(){ return age; } } return obj; } var person=fn(); console.log(fn().getName()); // 张三 console.log(fn().getAge()); // 23