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体系来跟踪数据。这样只要对象实例被销毁,相关信息也会被销毁,保证了信息的私有性。