Javascript学习之简单了解GC垃圾回收机制

136 阅读3分钟

我正在参与掘金创作者训练营第6期,点击了解活动详情

内存管理

不同于一些底层语言例如c语言,在javascript语言中,创建变量的过程时就自动进行了分配内存,并且在不使用它们时有一个自动释放的操作,释放的过程被称为垃圾回收。

内存生命周期

几乎所有编程语言的生命周期都分为以下几步

分配需要的内存

var a = 1;  // 给数据变量分配内存

var b = "bbb";  // 给字符串分配内存

var c = {
    d: 1,
    e: null
};  // 给数组及其包含的值分配内存

function f (g) {
    return f;
};  // 给函数分配内存

使用分配的内存

对分配的内存进行读写操作,这个操作可能是写入一个变量或者一个对象的属性值。

使用完成后不需要时释放该内存

分配给对象以及变量的内存在不使用后进行释放以便下一次使用,避免耗尽计算机内存造成崩溃。

垃圾回收的方法

引用计数法

介绍

垃圾回收算法主要依赖于引用的概念。在内存管理的环境中,一个对象如果有访问另一个对象的权限(隐式或者显式),叫做一个对象引用另一个对象。例如,一个 Javascript 对象具有对它原型的引用(隐式引用)和对它属性的引用(显式引用)。

简单来说,当一个对象没有被其他对象引用到它,此时这个对象处于一个0引用的状态,它就会被垃圾回收机制回收。

也就意味着,当一个变量被引用时,此时引用次数+1;当该变量的引用被清除时,引用次数-1;当引用次数变成0时,将会释放它的内存。

let a = 1;  // 1的内存被a引用,引用次数+1
a = 2;  // 1的内存被清除引用,引用次数-1

let b = a;  // 2的内存先后被a和b引用,引用次数为2

循环引用问题

在前面我们已经知道了,当变量的引用次数变为0时,就会被释放内存,那么如果对象互相被引用就永远不会被回收,执行多次后将会造成很严重的内存泄漏。

function test() {
    let obj1 = {};
    let obj2 = {};
    obj1.a = obj2   // obj1 引用 obj2
    obj2.a = obj1   // obj2 引用 obj1
}
test()

解决方法:函数结束时把对象指向null

obj1 = null;
obj2 = null;

标记引用法

为了避免出现循环引用的问题,Netscape Navigator 4.0 开始采用标记清除法。

垃圾回收机制会在运行的时候,会从根开始,找到所有从根开始引用的对象,然后找引用的对象引用的对象....然后给存储在内存里的所有变量都加上标记,同时会去掉环境中已经被标记为引用的变量。去掉之后,再被标记的变量就是可以被删除的变量,最后垃圾回收清除标记的变量回收内存空间,就完成了垃圾回收。

总结

本文简单介绍了两种垃圾回收的方法,旨在帮助读者对javascript里GC垃圾回收机制有一定的了解。