Set集合是一种无重复元素的列表。Map集合内含多组键值对,集合中每个元素分别存放着可访问的键名和它对应的值。
Set集合
创建
调用new Set()创建Set集合,调用add方法向集合中添加元素,访问size属性可以获取集合中目前的元素数量。
在Set集合中,不会对所存值进行强制的类型转换,数字5和字符串”5”是作为两个独立元素存在。由于key1和key2不会转换成字符串,因而它们再Set集合中是两个独立的元素。
如果多次调用add方法,并传入相同的值作为参数,那么后续的调用实际上会被忽略。
可以用数组来初始化Set集合,Set构造函数会过滤掉重复的值以保证集合中的元素各自唯一。可以通过has方法检测Set集合中是否存在某个值。
Set构造函数可以接受所有可迭代对象作为参数,构造函数通过迭代器从参数中取值。
移除
调用delete()方法可以移除Set集合中的某一个元素,调用clear()方法会移除集合中所有元素。
Set集合的forEach方法
forEach方法的回调函数接受3个参数
Set集合中元素的值- 与第一个参数一样的值
- 被遍历
Set集合本身
Set集合没有键名,第一二个参数相等,保证其他forEach方法的一致性。
|
|
Set集合中的forEach方法中,第二个参数也与数组的一样,传递到回调函数中来指代this值。
将Set集合转换为数组
使用展开运算符(...)可以将Set集合(可迭代对象)转换为数组
Weak Set集合
将对象存储在Set的实例与存储在变量中完全一样,只要Set实例中的引用存在,垃圾回收机制就不能释放该对象的内存空间。
示例中将变量key设置为null,清除了对初始对象的引用,但Set集合却保留了这个引用。有时候可能需要当其他所有引用不再存在时,Set集合中的这些引用随之消失。
ES6引入了另外一个类型,Weak Set集合(弱引用Set集合)。Weak Set集合只会存储对象的弱引用,不可以存储原始值,集合中弱引用是对象的唯一的引用,则会被回收并释放相应内存。
- 创建
用WeakSet构造函数可以创建Weak Set集合,也向构造函数可以传入一个可迭代对象来创建Weak Set集合。集合支持3个方法add、has和delete。123456789101112let set = new WeakSet(),key = {};set.add(key);console.log(set.has(key));//移除对象key的最后一个强引用,Weak Set中的引用也自动移除key = null;let key1 = {},key2 = {},set1 = new WeakSet([key1, key2]);
WeakSet构造函数中,不接受任何原始值,否则会抛出错误。
两种Set类型的主要区别
- 在
WeakSet实例中,如果向add、has和delete这3个方法中传入非对象参数都会导致程序报错。 Weak Set集合不可迭代,所以不能用于for-of循环。Weak Set不暴露任何迭代器(例如keys和values方法)所以无法通过程序本身来检测其中内容。Weak Set不支持forEach方法,不支持size属性。
Map集合
Map类型是一种储存着键值对的有序列表,其中键名和对应的值支持所有数据类型。键名不会被强制转换成其他形式,其的等价判断通过Object.is方法实现。
创建
调用new Map()创建Map集合,调用set方法并传入键名和对应值作为两个参数。调用get方法传入键名可以获取对应的值,如果传入的键名不存在则会返回undefined。也可以向Map构造函数传入数组来创建一个Map集合,数组中每一个元素都是一个子数组,子数组中包含一个键值对的键名与值两个元素。
Map集合支持的方法
Map和Set集合有3个通用的方法
has检测指定键名在Map集合中是否存在delete从Map集合中删除指定键名及其对应的值clear移除Map集合中的所有键值对
Map集合也支持size属性,代表当前集合中包含的键值对数量。
Map集合的forEach方法
Map集合中forEach方法和Set集合的forEach方法类似,其回调函数接受3个参数
Map集合中元素的值- 值对应的键名
Map集合本身
|
|
也可以指定
forEach函数的第二个参数作为回调的this值
Weak Map集合
Weak Map类型是一种存储键值对的无序列表,键名必须是非null类型对象,键名对应的值可以是任意类型。
和Weak Set集合类似,Weak Map是弱引用Map集合,用于存储对象的弱引用,集合中保存的是对象的弱引用,如果弱引用之外不存在其他的强引用,引擎垃圾回收机制会自动回收这个对象,同时也会移除Weak Map集合中的键值对。但只有集合中的键名遵从这个规则,键名对应的值如果是一个对象,则保存的是对象的强引用,不会触发垃圾回收机制。
初始化
调用WeakMap构造函数创建一个Weak Map,通过set方法添加数据,通过get方法获取数据。也可以通过传入一个数组,数组内的元素为一个数组,该数组有两个元素构成,第一个是键名,传入的值必须是非null对象,第二个是键名对应的值,可以是任意值。12345678910111213141516171819let map1 = new WeakMap(),ele = document.querySelector('.ele');map1.set(ele, 'original');let value = map.get(ele);console.log(value); //'original'//移除ele元素ele.parentNode.removeChild(ele);ele = null;// Weak Map 集合为空let key1 = {},key2 = {},map2 = new WeakMap([[key1, 'hello'], [key2, 'world']]);console.log(map2.has(key1)); //trueconsole.log(map2.get(key1)); //'hello'支持的方法
Weak Map集合只支持两个可以操作键值对的方法:has和delete方法,has方法用于检测给定键在集合中是否存在,delete方法可以移除指定的键值对。和Weak Set一样,二者都不支持键名枚举,也不支持clear方法。私有对象数据
Weak Map集合一般用于储存DOM元素,还有一个实际的应用是存储对象实例的私有数据
在ES5中,可以通过下面这种模式创建一个接近真正私有数据的对象
Person又一个立即调用函数表达式生成,包括两个私有变量:privateData和privateId,privateData对象保存的是每个实例的私有信息,privateId则为每个实例生成一个独立的ID。当调用Person构造函数时,属性_id的值会加1,这个属性不可枚举,不可写,不可配置。
privateData对象保存了所有实例对应的名称,调用getName函数,即可通过this._id获取当前示例的ID,并以此从privateData对象提取实例名称。
这种方法最大的问题是,如果不主动管理,由于无法获知对象实例何时被销毁,因此privateData中的数据永远都不会消失。使用Weak Map集合就可以解决这个问题。
|
|
由于Person对象实例可以直接作为集合的键使用,无需维护一套ID体系来跟踪数据。这样只要对象实例被销毁,相关信息也会被销毁,保证了信息的私有性。