早期es5
用对象来模拟Set
,通过对象的属性来判断值是否唯一或者取值,但是用对象来模拟也会有很多问题,比如需要保证任意键不能被转为相同字符串等,所以es6
新增了Set
和Map
类型,不会存在强制类型转换。
-
Set
:是不包含重复值的有序列表
// 创建Set实例对象
let set = new Set();
// 使用add()方法添加项
set.add(5);
set.add("5");
// 重复添加被忽略
set.add(5);
//使用size判断长度
console.log(set.size); // 2
- 为什么
5
和“5”
不会判断为重复值?通过Set内部的比较Object.is()
来实现的 -
Object.is()
是ES6
引入解决严格相等运算符遗留的怪异问题的,比如:+0 === -0
相等,NaN === NaN
不相等 -
+0
-0
在Set
中判断为相等 -
Set
可以添加不同类型的值,不会强制类型转换来判断值是否重复 -
Set
如果重复add
了相同值,会被忽略 - 根据上面这个
add
的特性,可以使用Set
来去除数组中的重复值,初始化这个Set
的时候,会同时塞入两个2
,但是只会取第一次塞入的值,所以起到去重作用
let set = new Set([1,2,2]);
console.log(set); // 返回Set对象 Set(2) {1, 2}
// 将Set转成数组
let setArray = [...set]
console.log(setArray); // [1,2]
-
Set
构造器可以接受任意可迭代对象作为参数,使用迭代器来提取参数中的值,如果参数是个number
类型的数字,会报错。
let set = new Set('emoji');
console.log(set); // 返回Set对象 Set(5) {"e", ","m","o","j","i"}
- 使用
has()
检测值是否存在Set
中: - 使用
delete()
删除单个值、clear()
删除全部值
let set = new Set();
set.add(5);
set.add("5");
set.has("5"); // true,没有则返回false
set.delete("5"); // true,删除没有的值会返回false
set.clear(); // 值会被清空
-
Set
也有forEach
方法 - 和数组使用
forEach
唯一的差别是:回调函数中的参数键与值相同、第三个是Set
本身
let set = new Set([1, 2]);
let processor = {
output(key,value,ownerSet) {
console.log(key,value,ownerSet);
},
process(dataSet) {
dataSet.forEach((key,value,ownerSet)=> this.output(key,value,ownerSet));
}
};
processor.process(set);
// 1 1 Set(2) {1, 2}
// 2 2 Set(2) {1, 2}
Weak Set
- 只能包含对象等特殊Set,只允许存储对象弱引用(对象的弱引用在它自己称为该对象的唯一引用时,不会阻止垃圾回收)
因为Set
存储对象时存储的是对象的引用,所以当清除对象引用的时候,Set
中还是会存在对象的引用,理想的应该是删除一个引用,Set
中相同引用也被删除,不会影响垃圾回收占内存导致内存泄漏。
-
Map
:是键值对的有序集合,可以通过键访问到所需读取的对应值(提取数据)
// 创建一个Map实例对象
let map = new Map();
// 也可以这样初始化
let map = new Map([["name", "emoji"], ["year", 2019]]);
let key = {};
// 使用set(键值)添加项
map.set("name", "emoji");
map.set("year", 2019);
// 对象也能做为键值,但不会修改对象自身
map.set(key, 5);
// Map(2) {"name" => "emoji", "year" => 2019}
// 使用get通过键名来获取对应值
map.get("name"); // "emoji"
map.get("year"); // 2019
map.get(key); // 5
// 访问的键值不存在返回undefined
map.get("emoji"); // undefined
-
Map
和Set
一样有has()\delete()\clear()\size
方法和属性 -
Map
的forEach()
:
和Set
的区别在于接受的回调函数的参数不同,第一个是值第二个是键,第三个是Map本身 -
Weak Map
只能包含对象类型的键的特殊Map,创建对象的私有数据