Bootstrap

【JS】垃圾回收机制

JavaScript 中的垃圾回收机制(GC)

1. 垃圾回收相关概念

垃圾: 没有被引用的对象,就是垃圾对象。

垃圾回收:

  1. 销毁垃圾对象,释放内存,称为垃圾回收。
  2. 像C、C++ 等编程语言需要手动回收垃圾。
  3. 像Paython、JavaScript、Java 等编程语言自动回收。

变量的生命周期:(何时会被回收)

  1. 修改变量的值,变量不再引用某个对象,该对象变为垃圾
  2. 执行执行结束,变量自动销毁,原来所指向的对象不再被引用,变为垃圾。

2. 垃圾没有及时回收的后果

  1. 垃圾对象没有被清除,导致内存空间被占用, 造成内存泄漏。
  2. 内存空间越占越多,导致程序卡顿甚至死机。

3. JavaScript 垃圾回收的常见算法

  • 引用计数
  • 标记清除

引用计数(现在很少使用)

1. 原理

  1. 每个对象都有一个引用标记
  2. 增加对该对象的引用(给变量或属性赋值),该对象的引用标记+1
  3. 减少对该对象的引用(变量或属性该值,变量属性被销毁),该对象的引用标记-1
  4. 当引用标记为 0 的时候,该对象变为垃圾对象,被回收
var a = [10,20,30,40];	// 此时数组的引用计数是 1
var b = a;				// 数组引用计数变为 2
a = null;				// 修改变量 a 的值;  数组的引用计数变为 1
b = 10000;				// 修改变量 b 的值;  数组的引用技术变为0,被销毁
// 直接量  用完即销毁
[1000,2000,3000,4000,6000];

2. 优缺点:

  1. 垃圾回收及时,计算效率高
  2. 互相引用的两个对象,会永远无法被销毁,常驻内存,造成内存泄漏
var obj1 = {name:'x'};		// x引用计数是 1
var obj2 = {name:'y'};		// y的引用计数是 1

obj1.child = obj2;			// y引用计数是 2
obj2.child = obj1;			// x的引用计数是 2

// 修改变量 obj1的值; x引用计数是 1
// obj1 = null;
// 修改变量 obj2 的值; y的引用计数 1
// obj2 = null;

标记清除(常用)

1. 原理

  1. 系统不断循环执行标记清除操作
  2. 每次标记清除分为两个阶段:
    • 标记阶段:从全局对象开始,向下遍历属性以及属性的属性(树状递归遍历),能够访问到的对象,进行标记,称为可访问对象。
    • 清除阶段:线性遍历内存中所有的对象,将没有标记的对象就是垃圾,进行回收。
  3. 下一轮去掉所有对象的标记,进行重新标记清除

2. 优缺点

  1. 所有的垃圾对象都可以被回收,不会造成内存泄漏
  2. 不停地循环进行进行树状递归遍历,执行效率相对较低
var obj1 = {name:'x'};		// x标记
var obj2 = {name:'y'};		// y标记

obj1.child = obj2;			// y标记
obj2.child = obj1;			// x标记

//改变值,没有引用,没有标记
// obj1 = null;	
// obj2 = null;

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;