📅  最后修改于: 2023-12-03 15:24:52.132000             🧑  作者: Mango
在 JavaScript 中,我们经常会使用 Map 对象来保存键值对。但是有些情况下,我们可能需要更加高效地管理键值对,同时又不希望这些键值对影响到垃圾回收机制的工作。这时,我们可以使用 WeakMap。
WeakMap 是 ES6 中新增加的一种 Map 类型,它与 Map 的区别在于:
使用 WeakMap 的方式跟 Map 类似,可以通过 set() 方法设置键值对,通过 get() 方法获取值,通过 has() 方法判断键是否存在。
let wm = new WeakMap();
let key1 = {};
let key2 = {};
// 设置键值对
wm.set(key1, "value1");
wm.set(key2, "value2");
// 获取值
console.log(wm.get(key1)); // 输出:value1
// 判断键是否存在
console.log(wm.has(key2)); // 输出:true
需要注意的是,当 key1 和 key2 不被引用时,WeakMap 会自动将它们从键集合中删除,同时也会释放它们所引用的值。
WeakMap 最典型的应用场景是在一些需要缓存数据的场景中。比如说,我们需要在一个对象上保存一些元数据,但是这些元数据与该对象的生命周期没有必然的关联。如果使用 Map 来缓存这些元数据,就可能会导致对象被 Map 引用,从而无法被垃圾回收机制回收。
let cache = new Map();
function computeValue(obj) {
if (cache.has(obj)) {
return cache.get(obj);
}
let result = /* 复杂的计算逻辑 */;
cache.set(obj, result);
return result;
}
let obj1 = {};
let obj2 = {};
computeValue(obj1);
computeValue(obj2);
// 在这里,即使我们不再需要 obj1 和 obj2,它们仍然无法被回收,因为 cache 仍然在引用它们。
如果使用 WeakMap 来解决这个问题,就不会有这样的问题。
let cache = new WeakMap();
function computeValue(obj) {
if (cache.has(obj)) {
return cache.get(obj); // 获取缓存的值
}
let result = /* 复杂的计算逻辑 */;
cache.set(obj, result); // 将结果缓存起来
return result;
}
let obj1 = {};
let obj2 = {};
computeValue(obj1);
computeValue(obj2);
// 在这里,即使我们不再需要 obj1 和 obj2,它们仍然会被垃圾回收机制回收,因为 WeakMap 中的键是弱引用。
在另一些场景中,我们可能需要在一个对象上保存一些私有数据,但是又希望这些数据只能在对象自身中使用,外界无法访问,这时也可以使用 WeakMap。
let privateData = new WeakMap();
class Person {
constructor(name) {
this.name = name;
privateData.set(this, { creditCardNumber: "1234-5678-9012-3456" });
}
getCreditCardNumber() {
let data = privateData.get(this);
return data ? data.creditCardNumber : undefined;
}
}
let person = new Person("John");
console.log(person.name); // 输出:John
console.log(person.getCreditCardNumber()); // 输出:1234-5678-9012-3456
console.log(privateData.get(person)); // 输出:undefined
在这个例子中,我们使用 WeakMap 来保存一个对象的私有数据,这些数据对外部是不可见的,只能在对象自身的方法中使用。这样可以有效地防止数据泄漏,增强了程序的安全性。
WeakMap 是 JavaScript 中一种特殊的 Map 类型,它具有高效、安全的特点,特别适用于一些需要缓存数据或者保存私有数据的场景中。注意,由于 WeakMap 的键是弱引用,因此可能会影响您程序的可读性和可维护性,因此请根据具体场景谨慎使用。