您的位置:首页 > Web前端 > JavaScript

高程笔记-总结从javascript内存空间引出的1mol多问题

2017-11-27 20:57 351 查看

写在前面

在看与js内存相关的资料(以高程为主)时,由内存引出的一系列的知识点和问题使我写下这篇笔记。梳理一下知识点:

js内存空间(栈内存、堆内存)->内存空间管理的垃圾收集机制->解除引用->垃圾收集机制方式(标记清除、引用计数)->引用计数->循环引用

js内存空间

基本类型值

有固定的大小,往往都保存在栈(stack)内存中。我们可以直接操作保存在栈内存空间的值,因此基本类型值都是按值访问。

引用类型值

没有固定大小,往往都保存在堆(heap)内存中。JavaScript不允许直接访问堆内存中的位置,因此我们不能直接操作对象的堆内存空间。在操作对象时,实际上是在操作对象的引用(或者说是指向对象的指针)而不是实际的对象。因此,引用类型的值都是按引用访问的。



内存管理与垃圾收集机制

对于内存管理问题,javascript中所需内存的分配以及无用内存的回收完全实现了内存的管理,通过自动垃圾收集机制实现内存的回收,正如我们知道的javascript内存生命周期:内存分配->使用内存->内存释放,执行垃圾收集机制就是为了内存释放这一步。

垃圾收集机制

原理:垃圾收集器按照固定的时间间隔(或代码执行中预定的收集时间)周期性的查找那些不再继续使用的变量,然后释放其占用的内存。

解除引用

垃圾收集机制在查找那些不再继续使用的变量,并释放其占用的内存空间。那些不再继续使用的变量是指解除了引用的变量。解除引用的作用是让值脱离执行环境,以便收集器下次运行时将其收回。

对于局部变量,它们会在离开执行环境时被解除引用

对于大多数全局变量,一旦数据不再有用,应当通过将值设置为null来释放其引用,因为在局部作用域中,当函数执行完毕,局部变量也就没有存在的必要了,因此垃圾收集器很容易做出判断并回收。但是全局变量什么时候需要自动释放内存空间则很难判断,当然我们最好避免使用全局变量,确保性能。

垃圾收集方式(标记清除、引用计数)

标记清除

javascript中最常用的垃圾收集方式

原理:

垃圾收集器在运行时会给内存中的变量都加上标记,然后会去掉环境中的变量的标记以及被环境中的变量引用的变量的标记。此后,再被加上标记的变量将视为准备收集的变量(原因是环境中的变量已无法访问到这些变量了),最后,垃圾收集器销毁那些带标记的值并回收它们所占的内存空间。

引用计数

原理:

当声明一个变量并将一个引用类型值赋给该变量时,这个值的引用次数就为1,该值又被赋给另一个变量时引用次数加1,相反,若包含该值的引用的变量取得其他一个值时引用次数减1。当这个值的引用次数为0时说明无法再访问这个值了,该值占用的内存空间就会被收集,当垃圾收集器下次再运行时,它就会释放引用次数为0的值所占的内存空间。

引用计数可能会导致的问题:循环引用

js高程给出的栗子:

function problem() {


var objectA = new Object();


var objectB = new Object();


objectA.someOtherObject = objectB;


object.anotherObject = objectA;


}


objectA和objectB相互引用,如果是以标记清除的方式进行垃圾收集,函数执行完毕,两个对象都离开了作用域,因此不存在相互引用的问题。如果是以引用计数的方式进行垃圾收集,这两个对象的引用次数就都是2(循环引用),函数执行完毕,两个对象将继续存在,因为他们的引用次数永远都不为0,就会造成内存泄漏问题(内存无法被回收)。正因为有这个严重的问题,引用计数基本上被标记清除所替代。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript
相关文章推荐