1. set
类似数组,但是成员唯一,没有重复值,可以用来做数组去重(常见),其中的值是精确值,1和"1"不同 可以接受数组作为构造参数。可迭代。
属性
size: 成员数
方法
add: 添加值,并返回set本身 delete:删除值,通过value删除,返回boolean判断是否成功 has:返回boolean,判断是否在set中 clean:清楚所有成员
遍历方法
keys, values, entries, for of(不能使用for in), forEach
2. weakset
类似set,但是成员只能是对象(null除外),不可迭代,不可清空 没有size属性,没办法遍历成员, 所有的成员都是弱引用,随时可能消失,便利机制无法保证成员的存在,所以不能遍历,但是有一个用处,就是储存dom节点,不用担心这些节点从文档移除的时候,会引发内存泄漏或业务场景问题。
3. Map
类似object,但是可以用任何值作为一个键名,类似于值---值这样的对应概念,是一种更完善的hash结构,更适合作为数据映射。可迭代
方法
get:获取对应value set:设置对应key-value has:判断是否有 delete:删除指定key
遍历方法
几乎同set,但是遍历顺序是插入顺序,map也能转数组
4. weakMap
与map结构类似,但是键名必须是对象(null除外),不可迭代,不可清空 它的设计目的在于,想在某些对象上储值,但是这会形成对象应用,改变原对象,如下
const e1 = document.getElementById('foo');
const e2 = document.getElementById('bar');
const arr = [
[e1, 'foo 元素'],
[e2, 'bar 元素'],
];
// e1,e1被arr引用了,一旦不需要这两个对象,就需要手动删除引用
// 删除
arr[0] = null
arr[1] = null
// 这样不方便,如果忘了删就会引起内存泄漏
weakMap键名弱引用,只要所引用的对象的其他引用被清除,gc就会回收对象内存,也就是说,一旦不需要,weakmap对应键值对就能自动消失,无需手动删除。 例如挂在dom元素上的数据,dom元素消失的时候,对应weakmap键值对纪录也会自动移除,释放内存
// 使用场景
var arr = [1,2,3]
var wm = new WeakMap()
wm.set(arr, 22)
// 直接清除arr
arr= null
// 此时weakmap没有阻止垃圾的回收,自动也删除了对应键值
但是这个所谓的移除,在浏览器上去实现的话,你还是能看到的
所以更好的方式,是在nodejs环境去查看内存是否被回收,
node --expose-gc # 开启手动回收垃圾机制
// 手动执行一次垃圾回收,保证获取的内存使用状态准确
> global.gc();
undefined
// 查看内存占用的初始状态,heapUsed 为 4M 左右
> process.memoryUsage();
{ rss: 21106688,
heapTotal: 7376896,
heapUsed: 4153936,
external: 9059 }
> let wm = new WeakMap();
undefined
// 新建一个变量 key,指向一个 5*1024*1024 的数组
> let key = new Array(5 * 1024 * 1024);
undefined
// 设置 WeakMap 实例的键名,也指向 key 数组
// 这时,key 数组实际被引用了两次,
// 变量 key 引用一次,WeakMap 的键名引用了第二次
// 但是,WeakMap 是弱引用,对于引擎来说,引用计数还是1
> wm.set(key, 1);
WeakMap {}
> global.gc();
undefined
// 这时内存占用 heapUsed 增加到 45M 了
> process.memoryUsage();
{ rss: 67538944,
heapTotal: 7376896,
heapUsed: 45782816,
external: 8945 }
// 清除变量 key 对数组的引用,
// 但没有手动清除 WeakMap 实例的键名对数组的引用
> key = null;
null
// 再次执行垃圾回收
> global.gc();
undefined
// 内存占用 heapUsed 变回 4M 左右,
// 可以看到 WeakMap 的键名引用没有阻止 gc 对内存的回收
> process.memoryUsage();
{ rss: 20639744,
heapTotal: 8425472,
heapUsed: 3979792,
external: 8956 }
react中的事件绑定就是用这个实现的
5. 是否可迭代
for in 可以作用于数组(获取下标),对象(获取key),但是不能作用于map,set,weakSet,weakMap,但是使用时不会报错。 for of 可以作用数组(获取value),map(item会变成键值对数组),set(获取value),不能作用于weakMap,weakSet,对象,原因都是他们是不可迭代的,会报错
weak的设计主要目的
是为了解决内存泄漏的问题,保证垃圾回收机制能准确回收用不到的变量,例如map的键是一个很大的dom对象,然后dom没了,这时候,dom变量的空间无法回收,因为被map的其中key所占用了,造成内存泄漏,但是如果是weakmap,就不会阻止垃圾回收机制。 参考: 介绍下 Set、Map、WeakSet 和 WeakMap 的区别