在前几天的一篇闭包文章中我们简单的介绍了一下闭包,但是并没有深入的讲解,因为闭包涉及的知识点比较多,为了能够更好的理解闭包,今天讲解一下关于js中的回收机制。
在初识闭包一文中我说过js中有回收机制这么一回事,让我们一起回顾一下,并且深入的了解js中的回收机制到底是怎么一回事。
function a(){
var num = 10;
return function(){
num ++;
console.log(num);
}
}
a()(); //11
a()(); //11
按理说第二次执行函数a的时候应该打印出12才对,但是打印的却是11,这难道不能说明js在这其中做了什么手脚吗?按照正常逻辑我们一起来分析分析。
首先来看看我们的理解:
//我们在函数a中返回了一个匿名函数,在这个匿名函数中我们num++了一下,然后我们在函数外面执行了这个匿名函数函数,(第一括号执行函数a第二个括号执行这个rutrun回去的函数)
//现在num是11,然后我们又执行了一次这个函数,你们应该是12吧,为什么不是呢?
-------------------------------------实际js的执行-----------------------------------
但是js的设计者为了让没有必要的变量保存在内存中,(我们写的任何变量都是需要内存空间的),什么叫没有必要的变量?也就是说你不在需要这个变量的时候它就会被销毁?那么你肯定会问js怎么知道那些变量是我们不需要的哪些是我们需要的。所以js为了知道哪些变量需要保存下来,哪些不需要保存下来,会进行一些判断。接下来我们就一起看看js是怎么判断的。
1.在js中定义的全局变量是不会被销毁的,因为我们随时都可能会用到这个变量,所以不能被销毁。
2.但是在函数中定于的变量就不一定了,而且由于在函数的定义的变量的生命周期在执行完这个函数就销毁的原因自然就保存不了上一次的值。
2.1但是并不是说函数就真的保存不了上一次的值,因为有的时候我们确实需要上一次的值,所以js判断是否需要保存上一次变量的值的时候就会遵守这样的一个规则。
规则
如果这个函数有被外部的变量引用就不会销毁(这句话说的不够准确,下面代码会一步一步解释),否则销毁。怎么理解这句话呢?
function a(){
var b = 0;
return function(){
b ++;
console.log(b);
}
} var d = a();
d();//1
d();//2
函数a被变量变量d引用,更准确的说是函数a里面的那个匿名被变量d所引用,因为变量d等于的是函数a执行完成后的值,而函数a执行完以后又因为函数a返回了那个匿名函数,所以准确的说是变量d等于匿名函数。而这个匿名函数因为使用了函数a中的变量b并且还被变量d所引用,所以就形成了一个闭包,只要这个变量d不等于null的话,那么那个变量b会一直保存到变量d中不会被销毁。
总结:
1、如果一个对象不被引用,那么这个对象就会被GC回收;
2、如果两个对象互相引用,但是没有被第3个对象所引用,那么这两个互相引用的对象也会被回收。
如果你想更加深入学习闭包,那么我推荐你看一下关于在for循环中绑定事件打印变量i是最后一次的问题这篇文章。