【JS】—垃圾回收机制

一、指令材料

1.定义

JavaScript(JS)的垃圾回收机制是一种自动管理内存的过程,它有助于释放不再使用的内存,以避免内存泄漏和提高程序的性能。
JavaScript的垃圾回收机制是一种自动管理内存的方式,以确保不再被引用的对象可以被垃圾回收,释放内存。

2.分类

2-1. 引用计数算法

引用计数算法通过跟踪每个对象被引用的次数来决定何时回收内存。当一个对象的引用计数为零时,它就会被垃圾回收.

2-2. 循环引用

循环引用是一种特殊情况,其中两个或多个对象互相引用,导致它们的引用计数不会降为零。这时,垃圾回收需要使用更复杂的算法来检测并处理循环引用。

2-3. 标记清除算法

标记清除算法通过标记所有从根对象(通常是全局对象)可达的对象,然后清除未标记的对象来回收内存。

二、 限定条件

JavaScript的垃圾回收机制主要涉及对象的管理,而基本数据类型通常不涉及垃圾回收,因为它们是简单的值,而不是对象。JavaScript的垃圾回收机制更关注于复杂数据类型,如对象和数组。

  1. 数字(Number): 基本数据类型的数字是不需要垃圾回收的,因为它们只是简单的数值,没有引用其他对象或数据。
let x = 42; // 基本数据类型的数字
  1. 字符串(String): 基本数据类型的字符串也不需要垃圾回收,因为它们是不可变的,没有内部引用需要跟踪。
 let name = "John"; // 基本数据类型的字符串
  1. 布尔值(Boolean): 基本数据类型的布尔值也不需要垃圾回收,因为它们只表示真或假。
let isLogged = true; // 基本数据类型的布尔值
  1. 空值(null)和未定义(undefined): 这些特殊的基本数据类型表示缺少值或未定义的值。它们也不需要垃圾回收。
let emptyValue = null; // 空值
let undefinedValue; // 未定义

三、做练习题

1. 引用计数算法

// 把 {name: ‘John’} 代指A
//  A 对象被obj1 引用1次,A 引用计数=1次
let obj1 = { name: 'John' };
//  A 对象被obj2 引用1次,A 引用计数=2次
let obj2 = obj1; 


// 解除obj1 的引用对象A, A 引用计数 = 1 次
obj1 = null;
// 解除obj2 的引用对象A, A 引用计数 = 0 次
obj2 = null; 

// 对象A 没有被任何变量引用,将被垃圾回收机制回收

总结归纳:

  1. 引用计数是指一个对象的堆内存空间被引用了几次
  2. 通过=号,给变量赋值对象,引用增加
  3. 通过=号,给变量赋值为null, 解除对象的引用

2-1. 循环引用

function createCircularReference() {
  // 把 {} 代指 A, A 被obj1 引用1次, A的引用计数 = 1次
  let obj1 = {}; // 
  // 把 {} 代指 B, B 被obj1 引用1次, B的引用计数 = 1次
  let obj2 = {}; // 
  // B 被 obj1.circularRef 引用1次, B的引用计数 = 2次
  obj1.circularRef = obj2; 
  // A 被 obj2.circularRef 引用1次, A的引用计数 = 2次
  obj2.circularRef = obj1; 
  // 这里有一个循环引用,即obj1和obj2互相引用
}

// 当函数执行完毕后,obj1和obj2都会离开作用域,
// 但由于它们互相引用,它们的引用计数不会降为零,
// 垃圾回收需要检测和处理这种循环引用```

总结归纳:

  1. 循环引用,引用计数不会降为零
  2. 循环引用是通过两个对象的属性,相互赋值另外一个对象,实现相互引用

1和2-1对比归纳:

  1. 大括号中无论是否有值,都会开辟新的内存空间
  2. 绑定引用和解除引用都使用=号,

2-2. 手动解除引用

你可以通过将循环引用的其中一个对象设置为null来手动解除引用。这将打破循环引用,允许垃圾回收器正确地识别这些对象并释放它们。

// 循环引用
const obj1 = {};
const obj2 = {};
obj1.ref = obj2;
obj2.ref = obj1;

// 手动解除引用obj1.ref = null;
obj2.ref = null;

总结归纳:

  1. 绑定引用和解除引用的属性或对象,要保持一致性

2-3. WeakMap和WeakSet 解除引用

JavaScript提供了WeakMap和WeakSet数据结构,它们允许你存储弱引用(不会阻止垃圾回收的引用)。这些数据结构不会阻止对象被回收,因此可以用于解决循环引用问题。当你不再需要这些引用时,它们会自动被垃圾回收

const obj1 = {};
const obj2 = {};

const weakMap = new WeakMap();
weakMap.set(obj1, obj2);
weakMap.set(obj2, obj1);

// 当不再需要循环引用时,它们会被自动释放

总结归纳:

  1. 使用 weakMap方法,内存变成弱引用,不受引用计数的影响,自动被回收站回收。

3. 标记清除算法

标记清除算法通过标记所有从根对象(通常是全局对象)可达的对象,然后清除未标记的对象来回收内存。

// 标记所有能够从根对象访问到的对象,通常包括全局变量、当前调用栈中的变量等。标记的对象会被标记为“活动”
function createUser() {
  let user = {
    name: 'Alice',
    age: 30  
  };
  return user;
}
// 遍历:垃圾回收器遍历整个对象图,标记所有与活动对象相互引用的对象,以确保不会因为被引用而被清除。
let userData = createUser(); 
// 现在userData不再引用对象
userData = null; 

// 当userData变为null后,活动对象被解除引用
// 垃圾回收会将这个对象createUser()清除

总结归纳:

  1. 标记全局变量下对象,为活动对象
  2. 遍历查询出,哪些活动对象被引用,防止被垃圾回收

总结规律:

  1. 引用计数是指一个对象的堆内存空间被引用了几次
  2. 通过=号,给变量赋值对象,引用增加
  3. 通过=号,给变量赋值为null, 解除对象的引用
  4. 循环引用是通过两个对象的属性,相互赋值另外一个对象,实现相互引用
  5. 循环引用,引用计数不会降为零
  6. 手动解除引用,通过把基本数据类型赋值给变量,解除变量和对象的引用关系
  7. 对象弱引用,使用weakMap和WeakSet方法实现两个对象的弱引用,使用完成后允许垃圾回收
  8. 标记全局变量下对象,为活动对象
  9. 遍历查询出,哪些活动对象被引用,防止被垃圾回收

四、建立新学的知识与旧知识之间的关联

1. js的垃圾回收机制和 delete 删除对象的属性

  1. js的垃圾回收机制,把代码中没有被引用的对象,自动清除该对象所占用的内存空间;delete 删除对象的属性
  2. 两者之间的区别
  • 一个清除未被引用对象的内存空间;一个是删除对象的属性
  • 一个自动清除;一个是手动删除
  • 两者的本质:都是清除掉不需要的东西,达成某个功能
// {name:'xiao'} 被obj1 引用1次,{name:'xiao'} 的引用计数 = 1
let obj1 = {name:'xiao'} 
// 解除 ob1 和 {name:'xiao'} 引用关系, {name:'xiao'}的引用计数 = 0, {name:'xiao'} 将被垃圾回收
obj1 = null
let params = {
	id: 123,
	name: 'xiao'
	phone: '123456789'
}
// 业务需求是,新增时,删除id
if (state === 'add'){
	delete params.id
}

2. 引用计数算法(暂时想不到与那个旧知识关联,日后补充)

3. 标记清除算法(暂时想不到与那个旧知识关联,日后补充)

五、 转换表述

1. js的垃圾回收机制

垃圾回收机制,就是我们平时去吃火锅时,每一盘菜就是就是一个正在被使用的内存,当菜被吃完后,服务员会把空盘子自动拿走,以保证桌面整洁和提高用户体验。

2. 引用计数算法

引用计数算法就像我们吃完火锅,一包卫生纸盒,给每个人都发一张,直到卫生纸都发完了,只剩下空纸盒,它就会被垃圾回收。引用计数的本质是,该物品(或对象)对某人或事物,还有没有它的价值。
【JS】—垃圾回收机制_第1张图片

3. 循环引用

循环引用就是两个正在热恋的年轻人,两个人相互吸引,都离不开对方,脑海中无时无刻在想着对方,所以引用计数永远不会为零,直到他们分手时,他们之间的引用计数才会变成0

4. 标记清除算法

标记清除算法就是书桌上有很多东西,比如零食、玩具、书本、笔,然后现在妈妈让你写作业,把无关的东西收拾起来,零食、玩具就会被收拾起来(垃圾回收)。
标记清除算法的本质,把没有使用的东西清除掉。

【JS】—垃圾回收机制_第2张图片

你可能感兴趣的:(JavaScript,javascript,开发语言,ecmascript)