继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

垃圾收集

largeQ
关注TA
已关注
手记 960
粉丝 92
获赞 585

我们都知道JavaScript具有自动垃圾收集机制,这也就是说,执行环境会管理代码执行过程中使用的内存。

这种垃圾收集机制的原理很简单:找出那些不再继续使用的变量,然后释放其占用的内存。

垃圾收集器必须跟踪那个变量有用哪个变量没用,对于不再有用的变量打上标记,以备将来收回其占用的内存。用于标识无用的策略可能会因实现而异,但具体到浏览器中的实现,则通常有两个策略。

一.标记清除

1.标记清除是JavaScript中最常用的垃圾收集方式。
2.当变量进入环境时,就将这个变量标记为“进入环境”,当变量离开环境时,则将其标记为“离开环境”。
3.可以使用任何方式来标记变量
4.垃圾收集器在运行时候会给存储在内存中的所有变量都加上标记。然后,它会去掉环境中的变量以及被环境中引用的变量的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,因为环境中的变量已经无法访问到这些变量了。最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并收回它们所占用的内存空间 。

二.引用计数

另一种不太常用的垃圾收集策略叫做引用计数
引用计数其实就是跟踪记录每个值被引用的次数。
1.声明一个变量并将引用类型值赋给改变量,这个值的引用次数为1;
2.如果同一个值又被赋给另一个变量,则改引用次数加1;
3.如果包含对这个值引用的变量又取另一个值,该引用次数减1;
4.当这个值得 引用次数为0时,说明无法访问这个值,将其占用的内存空间收回。
5.当垃圾收收集器 下次运行时,释放引用次数为0的值所占用的内存。

下面我们来看一个循环引用的栗子

function problem(){    var  objectA = new Object();    var  objectB = new Object();
                
    objectA.someOtherObject = objectB;
    objectB.anotherObject = objectA;
}

在这个例子 中,objectA和objectB通过各自属性相互引用,也就是说,这两个对象的引用次数都是2。

当采用标记清除策略时,由于函数执行完后,两个对象都离开了作用域,这种相互引用不存在问题。

当采用引用计数策略时,函数执行完毕后,但objectA和objectB依然存在,因为它们的引用次数永远不会为0,假如这个函数被多次调用,就会导致大量内存得不到回收。

所以说,引用计数策略会导致很多麻烦。

性能问题

垃圾收集器是周期性运行的,而且如果分配的内存数量很客观,那么回收工作量也是相当大的。
在这种情况下,确定垃圾收集的时间间隔是一个非常重要的问题。

JavaScript引擎的垃圾收集例程改变了工作方式:触发垃圾收集的变量分配,字面量和数组元素的临界值被调整为动态修正。

管理内存

JavaScript在进行内存管理及垃圾收集时面临一个问题:分配给Web浏览器的可用内存数量通常比分配给桌面应用程序的少。
这样做的目的是:防止运行JavaScript的网页耗尽全部系统内存而导致系统崩溃。
解除引用:为了在执行代码时只保存必要的数据,一旦数据不再有用,最好通过将其值设置为null来释放其引用。
这一做法适用于大多数全局变量和全局对象的属性。
局部变量会在它们离开执行环境时自动被解除引用。

我们来看看下面的栗子:

function createPerson(name){    var localPerson = new Object();
    localPerson.name = name;    return localPerson;
}var globalPerson = createPerson("Jimmy");//手工解除globalPerson的引用globalPerson = null;

在这个例子中lacalPerson是一个局部变量,它在createPerson()函数执行完毕后就离开了执行环境,不需要我们去为它解除引用,globalPerson是一个全部变量,我们通过给它设null来手动解除。

解除一个值的引用并不意味着自动收回该值所占用的内存,解除引用的真正作用是让值脱离执行环境,方便垃圾收集器器下次运行时将其收回。



作者:Passerbylll
链接:https://www.jianshu.com/p/029521eb3ed2


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP