weakMap
weakMap是Map的一种,但它有更多的限制,
1. WeakMap
和 Map
的第一个不同点就是,WeakMap
的键必须是对象,不能是原始值(number,string,symbol...)
2. WeakMap
不支持迭代以及 keys()
,values()
和 entries()
方法。所以没有办法获取 WeakMap
的所有键或值,这也表示无法直接获取到weakMap的内部值(打印),
- 不可被打印出内容
- 不能获取键值
- 无法迭代遍历
WeakMap
只有以下的方法:
weakMap.get(key) 读取一个值
weakMap.set(key, value) 设置一个键值
weakMap.delete(key) 删除一个键值
weakMap.has(key) 查询键是否存在
以上这些性质,说明了weakMap可以设置键值,但键必须是对象;不暴露键,没有预知键,就无法拿到对应的值;对weakMap的操作都是基于键,没有键就无法操作weakMap,这相等于拥有很高的保密性;
新建一个weakMap
// 新建一个弱映射
const wMap = new WeakMap();
// 新建一个对象作为弱映射的键
const obj = {
name: 'John'
};
// obj作为弱映射的键
wMap.set(obj, '这是一个weakMap');
console.log(wMap);
console.log(wMap.get(obj));// 这是一个weakMap
可以看到通过get方法拿到了obj对应的值,而直接打印则没有结果
‘weak’的特性
除了表面用法上的隐私性存值,weakMap还有一个重要的特性,
在JavaScript 引擎中,值在“可达”和可能被使用时,会保持在内存中,否则会被清除;
而对于weakMap,当这个对象存入了weakMap键中,被置空后该对象将会被从内存(和weakMap)中自动清除(节约内存)。
这个过程就相当于,在一个硬盘中,如果一个文件夹是空文件夹,在不节约空间的情况下(map的环境),空文件夹会被保留,而在节约空间的情况下(weakMap的环境),空文件夹被认为没有作用,被删除。
这种节省的能力一般会用在第三方库的引用,第三方库常常比较消耗内存,大多数情况下都是使用其一小部分功能,当一个第三方库被使用完后,删除引用它的对象(键),这个第三方库的其他内容也就无法访问到而被删除了
weakSet
和set一样,weakSet也是不重复的值的集合,但是它的值被限制为只能是对象,
- 与
Set
类似,但是我们只能向WeakSet
添加对象(而不能是原始值)。 - 对象只有在其它某个(些)地方能被访问的时候,才能留在
WeakSet
中。 - 跟
Set
一样,WeakSet
支持add
,has
和delete
方法,但不支持size
和keys()
,并且不可迭代。
- 只能存对象
- 对象没有被使用时,最后会weakSet被删除
- 不能被读取值,也不能遍历,只能对其添加,删除和判断
以上这些性质表示,weakSet可以存值,但不可读取值,只能判断是否有这个值,和删除一个值,
新建一个weakSet
// 新建一个弱集合
const wSet = new WeakSet();
// 新建对象作为弱集合的值
const user1={
name :'张三'
}
const user2={
name :'李四'
}
const user3={
name :'王五'
}
// 将user1,user2作为弱集合的值
wSet.add(user1);
wSet.add(user2);
wSet.has(user1);// true
wSet.has(user3);// false
用户1进入过wSet,可以得到true的判定,用户3则没有被wSet添加,返回了false,
这个特性可以用来表示用户是否访问了网站
一个复杂点的数据结构
// 新建一个弱映射
const wMap = new WeakMap();
// 新建一个映射
const map = new Map();
// 新建一个集合
const set = new Set();
// 新建一个对象作为弱映射的键,同时内容作为映射的值
const obj = {
name: 'John'
};
set.add(obj);
// 将obj对象的name作为map映射name键的值
map.set(obj.name,set);
// 在将map映射作为wMap映射obj对象的值
wMap.set(obj, map);
console.log('key:\t',obj,'\nvalue:\t',wMap.get(obj));
这是一个三层结构,当obj被清除时,后面的map和set都无法被访问了(都被清除),
总结
WeakMap
是类似于 Map
的集合,它仅允许对象作为键,并且一旦通过其他方式无法访问这些对象,垃圾回收便会将这些对象与其关联值一同删除。
WeakSet
是类似于 Set
的集合,它仅存储对象,并且一旦通过其他方式无法访问这些对象,垃圾回收便会将这些对象删除。
它们的主要优点是它们对对象是弱引用,所以被它们引用的对象很容易地被垃圾收集器移除。
完整代码展示
// 新建一个弱映射
const wMap = new WeakMap();
// 新建一个对象作为弱映射的键
const obj = {
name: 'John'
};
// obj作为弱映射的键
wMap.set(obj, '这是一个weakMap');
console.log(wMap);
console.log(wMap.get(obj));// 这是一个weakMap
// 新建一个弱集合
const wSet = new WeakSet();
// 新建对象作为弱集合的值
const user1={
name :'张三'
}
const user2={
name :'李四'
}
const user3={
name :'王五'
}
// 将user1,user2作为弱集合的值
wSet.add(user1);
wSet.add(user2);
console.log(wSet.has(user1));// true
console.log(wSet.has(user3));// false
console.log(wSet);
// // 新建一个弱映射
// const wMap = new WeakMap();
// // 新建一个映射
// const map = new Map();
// // 新建一个集合
// const set = new Set();
// // 新建一个对象作为弱映射的键,同时内容作为映射的值
// const obj = {
// name: 'John'
// };
// set.add(obj);
// // 将obj对象的name作为map映射name键的值
// map.set(obj.name,set);
// // 在将map映射作为wMap映射obj对象的值
// wMap.set(obj, map);
// console.log('key:\t',obj,'\nvalue:\t',wMap.get(obj));