ES6新特性-Set、Map、Weak Set、Weak Map

494 阅读5分钟

ES6新特性-Set、Map

Set

1、ES6中提供了Set数据容器,这是一个能够存储无重复值的有序列表。

2、Set相关API

  • 可通过 const set=new Set() 可以创建Set对象
  • 或通过 const set=new Set([1,2,3]) 创建
  • set.add(x) 用来向set中添加数据项。 Set内部使用Object.is()方法来判断两个数据项是否相等,唯一不同的是+0和-0在Set中被判断为是相等的。
  • set.has(x) 用来判断set中是否包含某个数值
  • set.size 用来获取Set对象内部数据数量
  • set.delete(x) 用来删除set中的某个数值
  • set.forEach(()=>{}) 用来遍历set 回调函数的参数为元素值;元素索引;将要遍历的对象;
 let set = new Set([1,2,3,3,3,3]);
 set.forEach(function (value,key,ownerSet) {
     console.log(value);
     console.log(key);           
 })
  • set.clear() 用来清空set
  • Set中的key与value相同的,即set[x]=x
  • 也可以通过 [...arr]=set 的方式将set转为数组arr

Weak Set

出现的原因

Set在存放对象时,实际上是存放的是对象的引用,即Set也被称之为Strong Set。如果所存储的对象被置为null,但是Set实例仍然存在的话,对象依然无法被垃圾回收器回收,从而无法释放内存:

let set = new Set();
let key={};
let key2 = {};
set.add(key);
set.add(key2);
console.log(set.size); //2

key=null;
console.log(set.size); //2

因此,为了让对象key正常释放,可以使用Weak Set,此时,**存放的是对象的弱引用,当对象只被Set弱引用的话,并不会阻止对象实例被回收。**且Ser与Weak Set的用法几乎一致

Weak Set和Set之间的差异

  • 对于Weak Set实例,若调用了add()方法时传入了非对象的参数,则会抛出错误。如果在has()或者delete()方法中传入了非对象的参数则会返回false;
  • Weak Set不可迭代,因此不能用于for-of循环;
  • Weak Set 无法暴露出任何迭代器(例如 keys() 与 values()方法),因此没有任何手段可用于判断 Weak Set 的内容;
  • Weak Set没有forEach()方法;
  • Weak Set没有size属性;

Map

1.ES6中提供了Map数据结构,能够存放键值对,其中,键的去重是通过Object.is()方法进行比较,键的数据类型可以是基本类型数据也可以是对象,而值也可以是任意类型数据。

2.Map相关API

  • 初始化,与Set类似可let map = new Map()
//使用数组来创建Map
let map = new Map([['title','hello world'],['year','2018']]);
console.log(map.has('title')); //true
console.log(map.has('year')); //true
console.log(map.size); //2
  • 与Set相同,也拥有has('key'),delete('key')以及clear()方法
  • map.set('key','value') 用于添加键值对
  • map.get('key') 用于获取key='key'的值
 let map = new Map();
 map.set('title','hello world');
 map.set('year','2018');
 
 console.log(map.get('title')); // hello world
  • 与Set一样,Map也拥有forEach方法,该方法也接收一个回调函数,该回调函数有三个参数:元素值;元素索引;将要遍历的对象
 let map = new Map([['title','hello world'],['year','2018']]);
 map.forEach((value,key,ownerMap)=>{
     console.log(value);
     console.log(key);
 });
 
 hello world
 title
 2018
 year

Weak Map

出现的原因

Weak Map对Map而言,就像是Weak Set相对于Set一样:Weak Map(或者Weak Set)都是存储对象弱引用的方式,在Weak Map(或者Weak Set)中,所有的键都必须是对象(尝试使用非对象的键会抛出错误),而且这些对象都是弱引用,不会干扰到垃圾回收。当Weak Map中的键在Weak Map之外不存在引用时,该键值对会被移除。

Weak Map的使用

  • Weak Map的初始化
//
使用数组来创建一个Weak Map
let key = {};
let key2 = {};
let map = new WeakMap([[key,'hello'],[key2,'world']]);
console.log(map.get(key)); //hello
console.log(map.get(key2)); //world
  • has方法以及delete方法
let key2 = {};
let map = new WeakMap([[key,'hello'],[key2,'world']]);

map.delete(key);
console.log(map.has(key)); //false

Weak Map 的用法与局限性

  • 当决定是要使用 Weak Map 还是使用Map 时,首要考虑因素在于你是否只想使用对象类型的键。
  • 如果你打算这么做,那么最好的选择就是 Weak Map 。因为它能确保额外数据在不再可用后被销毁,从而能优化内存使用并规避内存泄漏。 要记住 Weak Map 只为它们的内容提供了很小的可见度,因此你不能使用 forEach() 方法、size 属性或 clear() 方法来管理其中的项。如果你确实需要一些检测功能,那么正规 Map会是更好的选择,只是一定要确保留意内存的使用。

小结

  1. Set是无重复值的有序列表,根据Object.is()来判断内部值的不相等。可用has()来判断某个值是否在Set中,或用size查看Set中有多少个值。Set还可以用forEach()进行遍历,来处理每个值。
  2. Map是有序的键值对,其中的键允许是任何类型。与 Set 相似,根据Object.is()来判断内部键的不相等,注意,数值1字符串1可以作为两个独立的键。使用set()方法能将任何类型的值关联到某个键上,并且该值此后能用get()方法提取出来。Map 也拥有一个size属性与一个forEach()方法,让项目访问更容易。
  3. Weak Set是只能包含对象的特殊 Set 。其中的对象使用弱引用来存储,因此不会屏蔽垃圾回收机制。但因为内存管理的复杂性, Weak Set的内容不能被检查。
  4. Weak Map 是只能包含对象类型的键的特殊 Map 。与 Weak Set 相似,键的对象引用是弱引用,因此当它是某个对象的仅存引用时,也不会屏蔽垃圾回收。当键被回收之后,所关联的值也同时从 Weak Map 中被移除。