这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战
前言
吃饱饭才有力气写代码~
今天偶然间看见窗外的青山绿水蓝天白云,突然就很感慨!程序员这个工作没有想象的那么轻松啊~除了每天的任务外还需要自我提升,虽然才开始不久,但是这个疲倦的感觉倒是很强烈。不过呢,不能轻易放弃,坚持一阵子一定会有收获的!开始今天的学习:JavaScript 的垃圾回收;
垃圾回收
JavaScript 是使用垃圾回收的语言,也就是在代码执行时执行环境会负责管理内存;相比较于 C 和 C++ ,它通过自动内存管理实现内存分配和闲置资源回收;基本的思路很简单,就是确定哪一个变量不会再使用,然后释放它的内存!
这个过程是周期性的,也就是说垃圾回收程序每隔一段时间就会自动运行,它其实是一个近似而且不是很完美的方案,因为哪个内存是否还有用并不能靠算法判定。
例如:函数中的局部变量,它会在函数执行时存在,栈内存会分配空间来保存相应的值,函数在内部使用了变量然后退出,此时就不再需要这个局部变量了,那它占用的内存就会被释放。但是并不是所有的时候都像函数里的局部变量那么明显,垃圾回收机制需要跟踪记录哪个变量还会使用,哪个变量不再使用。
标记清理
JavaScript 最常用的垃圾回收策略是标记清理;垃圾回收程序运行的时候会标记内存中存储的所有变量(具体的标记过程和标记方法的实现不重要,重要的是这种策略),之后它会把所有在上下文中的变量,以及被这些在上下文中的变量引用的变量的标记去掉,那剩下的就是可以被回收的变量。随后,垃圾回收程序做一次内存清理,销毁带标记的所有值并收回它们的内存。
引用计数
引用计数是另一种垃圾回收策略,它的思路是对每个值记录它被引用的次数,如声明变量并给它赋一个引用值时,这个值的引用数为1,如果同一个值又被赋值给另一个变量,那引用数加1,如果保存被该值引用的变量被其它值给覆盖了,那么引用数减1,当一个值的引用数为0就表示这个值可以被回收内存了。垃圾回收机制再运行的时候就会释放引用数为0的值的内存。
但是引用计数的策略有时候会有严重的问题,比如循环引用,即对象A有一个指针指向对象B,对象B也引用了A:
function problem(){
let objectA = new Object();
let objectB = new Object();
objectA.some = objectB;
objectB.other = objectA;
}
这个例子标记清理策略就能解决,因为函数结束后这两个对象都不在作用域中;而在引用计数策略下,它们在函数结束后还会存在,因为它俩的引用数永远不会为0。如果函数被多次引用,那就会有大量内存不会被释放。