理解强引用
let cat = { name: "Kitty" };
const pets = [cat];
cat = null;
console.log(pets); // [ { name: 'Kitty' } ]
通过将变量 cat 创建为对象,并把这个对象放入一个数组 pets 中,然后通过将它的值设置为 null 来删除其对原始对象的引用
尽管我们再也无法访问 cat 变量,但由于在 pets 数组和这个对象之间存在强引用关系,因此这个对象其实仍保留在内存中,并且可以通过 pets[0] 访问到它。 换句话说,强引用可以防止垃圾回收从内存中删除对象
理解弱引用
let pets = new WeakMap();
let cat = { name: "Kitty" };
pets.set(cat, "Kitty");
cat = null;
console.log(pets.get(cat)); // undefined
当我们通过将 cat 变量重新赋值 null 来覆盖对原始 cat 对象的引用时,由于内存中对原始对象的唯一引用是来自我们创建的 WeakMap 的弱引用,所以它不会阻止垃圾回收的发生。这意味着当 JavaScript 引擎再次运行垃圾回收过程时,cat 对象将从内存和我们分配给它的
可以用一个简单的例子来形容强引用与弱引用:
强引用:A牵着一条狗,他们之间通过狗链连着
弱引用:B指着A牵的狗,说:嘿,那有条狗,B指向那条狗,但他们之间没有是绑在一起的东西
当A放开狗链,无论B是不是还指着,狗都会跑掉(被垃圾回收器回收)
当B不再指着那条狗,狗还被A牵着,不会影响它是否跑掉
因此这里的关键区别就在于,强引用可以防止对象进行垃圾回收,而弱引用则不会
默认情况下,JavaScript 对其所有引用使用强引用,使用弱引用的唯一方法是使用 WeakMap 或 WeakSet。
WeakMap
WeakMap 结构与 Map 结构类似,也是用于生成键值对的集合。但是 WeakMap 只接受对象作为键名( null 除外),不接受其他类型的值作为键名
设计目的
1、有时想在某个对象上存放一些数据,但是这会形成对于这个对象的引用。一旦不再需要这两个对象,就必须手动删除这个引用,否则垃圾回收机制就不会是的对象占用的内存。
2、而WeakMap的键名所引用的对象都是弱引用,即垃圾回收机制不将该引用考虑在内。因此,只需要引用的对象的其他引用都被清除,垃圾回收机制就会释放的该对象所占用的内存。也就是说,一旦不再需要,WeakMap里面的键名和所对应的键值对会自动消失,不用手动删除引用。
WeakMap与Map的区别
Map:
let map = new Map();
let cat = { name: "Kitty" };
map.set(cat,'dog')
cat = null;
console.log(map); // Map { { name: 'Kitty' } => 'dog' }
WeakMap:
let wm = new WeakMap();
let cat = { name: "dog" };
wm.set(cat, "dog");
cat = null;
console.log(wm); // WeakMap { }
-
Map的键可以是任意类型,WeakMap只接受对象作为键,不接受其它类型的值作为键 -
WeakMap的键名所指向的对象,不计入垃圾回收机制(当出现WeakMap对对象的弱引用时,垃圾回收机制不会计入这个引用,也就是说,WeakMap对对象的引用不会妨碍原始对象被垃圾回收机制清除) -
Map可以被遍历,WeakMap不能被遍历