JavaScript是如何实现自动回收垃圾机制的?
它是通过确定哪个变量不会再使用,然后释放它占用的内存。垃圾回收程序不是无时无刻都在运行着,它会每间隔一段时间就会自动运行程序,清除哪些不再使用的内存。
那是如何检测哪个变量不再使用了呢?
通过标记清理和引用计数两种方法,可以进行检测哪个变量不再使用,但引用计数方法,在某些场景下却有一些弊端,比如循环引用,下面先讲一下引用计数,之后再讲一下标记清除。
基于引用策略的垃圾回收程序
function b(){
let obj={
name:"小黑",
age:18,
sex:"男",
} //对象被引用1次
return obj;
}
let obj=b();
console.log(obj);
obj=null;//对象被引用0次,下次执行垃圾回收程序时,会回收引用次数为0的对象
上面的对象最后被引用的次数是1次,为什么不是2次呢?
因为当函数调用完毕时,函数上下文出栈,函数里的所有变量都会自动被解除引用,所以现在该对象被引用的次数是1,在全局上下文中不会自动地解除对象的引用,如果需要解除引用,需要手动地将变量赋值为null。
引用计数的垃圾回收策略是有局限性的,来看一下下面的代码
function a(){
let obj1=new Object();
let obj2=new Object();
obj1.a=obj2;
obj2.a=obj1;
}
a();
当函数a被调用时,函数a的执行上下文被压入执行栈中,然后对函数体里的变量进行变量提升,之后执行代码,变量obj1创建了一个对象(这里给这个对象一个别名叫b,为了后面方便描述),变量obj2也创建了一个对象(别名a),然后obj1的属性a引用了对象obj2,obj2的属性a引用了对象obj1,此时对象a和对象b都被引用了2次。当函数a调用完毕时,函数a释放了它所占用的内存,但是对象a和对象b它们之间互相引用,所以对象a和对象b不会被垃圾回收程序回收内存!这就导致了内存泄漏。
正是因为引用计数会导致循环引用的问题,现在的垃圾回收程序大多采用标记清理的策略进行垃圾回收!
基于标记清理的垃圾回收程序
function a(){
let name="小黑";
return name;
}
function b(){
let obj={
name:"小红",
age:18,
sex:"男"
}
return obj;
}
let c=a();
let d=b();
console.log(name);
console.log(obj);
想一想哪个函数会造成内存泄漏?
函数a中的变量name是原始类型数据(String),当调用函数a时,把字符串的值"小黑"赋值给了变量c,调用完函数a后,函数a释放了它所占用的内存,所以函数a不会造成内存泄漏
函数b中的变量obj是引用类型(Object),当调用函数b时,将obj的地址值赋值给变量d,调用完函数b后,函数b释放了它所占用的内存,但0x0003的内存却没有被释放,因为全局变量d引用了0x0003,它是一个可达的对象。
function a(){
let obj1=new Object();
let obj2=new Object();
obj1.a=obj2;
obj2.a=obj1;
}
a();
调用函数a完后,全局上下文中没有变量引用它们,所以它们是不可达对象,等下次垃圾回收程序运行时,就会回收它们的内存。
function a(){
let obj1=new Object();
let obj2=new Object();
obj1.a=obj2;
obj2.a=obj1;
return{
aa:obj1,
bb:obj2,
}
}
var f=a();
调用函数a完后,全局上下文中变量f引用了它们,所以它们是可达对象,垃圾回收程序不会回收它们。
function a(){
let obj1={
name:"小黄"
}
let obj2={
name:"小白"
};
obj1.a=obj2;
obj2.a=obj1;
return{
aa:obj1,
bb:obj2,
}
}
var f=a();
f.aa=null;
大家想一想别名为b的对象会不会被垃圾回收程序回收?
答案是不会!,可以通过别名为a的对象,到达别名为b的对象,再看下面的代码
f.bb.a=null;
当把obj2.a=null时,全局上下文变量f再也到达不了别名为b的对象,所以等下次垃圾回收程序运行时,就会把别名为b的对象进行回收
到这里,我就把我自己对于垃圾回收机制的理解说完了,有什么不对的地方,欢迎大家指出^^
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!