weakMap是什么

前置

垃圾回收机制:垃圾回收机制会释放对象所占用的内存,但是垃圾回收机制的时机是不可控的

弱引用:即使有这个引用,垃圾回收机制在执行回收的时机也会将其回收

强引用:如果程序中有对一个对象的强引用,那么垃圾回收机制不会将其回收,我们手动将引用置为null,才可删除这个强引用

1
2
var obj = new Object();
obj = null; // 取消了对对象的强引用

以下是Map的使用,key = null 不会导致 key 的原引用对象被回收,因为这只解除了key对array对象的引用,但是map.set形成了map对array对象的强引用

1
2
3
4
5
6
7
8
let map = new Map();
let key = new Array(5 * 1024 * 1024);
// 建立map 对 key 所引用对象的强引用
map.set(key, 1);
// key = null 不会导致 key 的原引用对象被回收
key = null;
// 需要再解除map对key的引用才能使原引用对象被回收
map.delete(key);

定义

ES6的一个新特性

weakMap是和Map类似,Map的key对其引用的对象是强引用,weakMap就是字面意思,弱引用

1
2
const wm = new WeakMap()
wm.set(obj, 1)

 为什么要增加weakMap

特性

1.只接受对象做为key

2.key对其所引用的对象是弱引用

3.WeakMap 不像 Map,一是没有遍历操作(即没有keys()、values()和entries()方法),也没有 size 属性,也不支持 clear 方法。

  WeakMap只有四个方法可用:get()、set()、has()、delete()。

结论

所以WeakMap 可以帮你省掉手动删除对象引用的步骤,一旦不再需要,WeakMap 里面的键名对象和所对应的键值对会自动消失。

当你不能或者不想控制关联数据的生命周期时就可以考虑使用 WeakMap

 

应用场景

1. 在 DOM 对象上保存相关数据

传统使用 jQuery 的时候,我们会通过 $.data() 方法在 DOM 对象上储存相关信息(就比如在删除按钮元素上储存帖子的 ID 信息),jQuery 内部会使用一个对象管理 DOM 和对应的数据,当你将 DOM 元素删除,DOM 对象置为空的时候,相关联的数据并不会被删除,你必须手动执行 $.removeData() 方法才能删除掉相关联的数据,WeakMap 就可以简化这一操作:

1
2
3
4
5
6
7
let wm = new WeakMap(), element = document.querySelector(".element");
wm.set(element, "data");
let value = wm.get(elemet);
console.log(value);
//
element.parentNode.removeChild(element);
element = null;

2. 数据缓存

从上一个例子,我们也可以看出,当我们需要关联对象和数据,比如在不修改原有对象的情况下储存某些属性或者根据对象储存一些计算的值等,而又不想管理这些数据的死活时非常适合考虑使用 WeakMap

1
2
3
4
5
6
7
8
9
10
11
12
const cache = new WeakMap();
function countOwnKeys(obj) {
if (cache.has(obj)) {
console.log('Cached');
return cache.get(obj);
} else {
console.log('Computed');
const count = Object.keys(obj).length;
cache.set(obj, count);
return count;
}
}

3. 私有属性

1
2
3
4
5
6
7
8
9
10
11
12
13
const privateData = new WeakMap();
class Person {
constructor(name, age) {
privateData.set(this, { name: name, age: age });
}
getName() {
return privateData.get(this).name;
}
getAge() {
return privateData.get(this).age;
}
}
export default Person;

参考链接