JavaScript(JS)的垃圾回收机制是一种自动管理内存的过程,它有助于释放不再使用的内存,以避免内存泄漏和提高程序的性能。
JavaScript的垃圾回收机制是一种自动管理内存的方式,以确保不再被引用的对象可以被垃圾回收,释放内存。
引用计数算法通过跟踪每个对象被引用的次数来决定何时回收内存。当一个对象的引用计数为零时,它就会被垃圾回收.
循环引用是一种特殊情况,其中两个或多个对象互相引用,导致它们的引用计数不会降为零。这时,垃圾回收需要使用更复杂的算法来检测并处理循环引用。
标记清除算法通过标记所有从根对象(通常是全局对象)可达的对象,然后清除未标记的对象来回收内存。
JavaScript的垃圾回收机制主要涉及对象的管理,而基本数据类型通常不涉及垃圾回收,因为它们是简单的值,而不是对象。JavaScript的垃圾回收机制更关注于复杂数据类型,如对象和数组。
let x = 42; // 基本数据类型的数字
let name = "John"; // 基本数据类型的字符串
let isLogged = true; // 基本数据类型的布尔值
let emptyValue = null; // 空值
let undefinedValue; // 未定义
// 把 {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 没有被任何变量引用,将被垃圾回收机制回收
总结归纳:
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对比归纳:
你可以通过将循环引用的其中一个对象设置为null来手动解除引用。这将打破循环引用,允许垃圾回收器正确地识别这些对象并释放它们。
// 循环引用
const obj1 = {};
const obj2 = {};
obj1.ref = obj2;
obj2.ref = obj1;
// 手动解除引用obj1.ref = null;
obj2.ref = null;
总结归纳:
JavaScript提供了WeakMap和WeakSet数据结构,它们允许你存储弱引用(不会阻止垃圾回收的引用)。这些数据结构不会阻止对象被回收,因此可以用于解决循环引用问题。当你不再需要这些引用时,它们会自动被垃圾回收
const obj1 = {};
const obj2 = {};
const weakMap = new WeakMap();
weakMap.set(obj1, obj2);
weakMap.set(obj2, obj1);
// 当不再需要循环引用时,它们会被自动释放
总结归纳:
标记清除算法通过标记所有从根对象(通常是全局对象)可达的对象,然后清除未标记的对象来回收内存。
// 标记所有能够从根对象访问到的对象,通常包括全局变量、当前调用栈中的变量等。标记的对象会被标记为“活动”
function createUser() {
let user = {
name: 'Alice',
age: 30
};
return user;
}
// 遍历:垃圾回收器遍历整个对象图,标记所有与活动对象相互引用的对象,以确保不会因为被引用而被清除。
let userData = createUser();
// 现在userData不再引用对象
userData = null;
// 当userData变为null后,活动对象被解除引用
// 垃圾回收会将这个对象createUser()清除
总结归纳:
总结规律:
// {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
}
垃圾回收机制,就是我们平时去吃火锅时,每一盘菜就是就是一个正在被使用的内存,当菜被吃完后,服务员会把空盘子自动拿走,以保证桌面整洁和提高用户体验。
引用计数算法就像我们吃完火锅,一包卫生纸盒,给每个人都发一张,直到卫生纸都发完了,只剩下空纸盒,它就会被垃圾回收。引用计数的本质是,该物品(或对象)对某人或事物,还有没有它的价值。
循环引用就是两个正在热恋的年轻人,两个人相互吸引,都离不开对方,脑海中无时无刻在想着对方,所以引用计数永远不会为零,直到他们分手时,他们之间的引用计数才会变成0
标记清除算法就是书桌上有很多东西,比如零食、玩具、书本、笔,然后现在妈妈让你写作业,把无关的东西收拾起来,零食、玩具就会被收拾起来(垃圾回收)。
标记清除算法的本质,把没有使用的东西清除掉。