Set 和 Map是ES6新增的两种数据结构,在一些比较复杂的业务场景中,Map和Set能给我们提供很大的帮助;
一、Map:用于存储键值对
1.声明
const map = new Map()
Map对象可以保存键值对
const map = new Map([
['a','b'],
[{},777],
[123,555],
[undefined,6666]
])
console.log(map)
// 参数传递一般都是二维数组的形式,子数组只能有两项,第一项为键名,第二项为键值
2.方法
方法名 | 说明 |
---|---|
set(key,value) | 添加一个键值对 map.set( 1 , 'one' ) |
get(key) | 根据存储的键(key)来获取值(value)map.get(1) //one |
has(key) | 判断Map对象中是否存在key,返回true或false |
delete(key) | 通过键从Maori中移出对应的数据 |
clear() | 将这个map中所有的元素删除 |
size | 返回map中所包含的键值对个数 |
keys() | 返回键名的遍历器 |
value() | 返回键值的遍历器 |
entries() | 返回键值对的遍历器 |
forEach() | 使用回调函数遍历每个成员 |
3.使用
使用for..of 遍历key集合和value集合,键值对集合
const map = new Map()
map.set(1, 'aaa');
map.set(2, 'bbb');
map.set(3, 'ccc');
console.log(map.keys());
console.log(map.values());
for (const item of map.keys()) {
console.log(item);
}
for (const item of map.values()) {
console.log(item);
}
for (const item of map.entries()) {
console.log(item); //[1,'aaa'],//[2,'bbb'],//[3,'ccc']
}
forEach():有三个参数(value,key,map本身)
map.forEach((item, index, M) => {
console.log(item, index, M);
//aaa, 1, Map(3) {1 => 'aaa', 2 => 'bbb', 3 => 'ccc'}
});
4.选择Map还是Object
Map和Object都是用于键值对存储,我们需要了解它们之间的区别,方便在开发的时候进行选择
- 内存开销:在引擎层面上,Map 和object的实现区别很大,- 般来说,键值对存储的内存开销是随着键值对数量线性增长的。不过对于大部分浏览器来说,Map 在内存开销上还是略胜一筹, 粗略计算,Map 比object减少50%的内存开销,也就是说,同样的内存,Map 可以存储更多键值对。
- 插入性能:对于Map和object,一个插入操作不会被键值对数量所影响,但Map的速度会稍微快于0bject,如果你的代码有大量插入操作,建议选择Map。
- 查询性能:某些情况下,浏览器会优化object的存放位置(比如,有连续的整数属性) ,而在Map中这是不可能的,因此,如果你有大量查询,建议使用object。
- 删除性能:删除操作是一 件很可怕的事情,如果有删除需要,建议使用伪删除,将该属性赋值为undefined或者null。如果真的有删除需要,Map 的删除性能会更快一些。
二、Set:存储不重复的数据
1.声明
const set = new Set()
const set = new Set([1,2,3,3,5,1])
2.方法(与Map类似)
方法名 | 说明 |
---|---|
add(val) | 添加某个值,返回Set结构本身 set.add(1) |
has(val) | 返回布尔值,表示该值是否存在于set集合中 set.has(1) |
delete(val) | 删除某个值,删除成功返回true,反之返回false; set.delete(1) |
clear() | 清除所有成员,没有返回值 set.clear() |
size | 返回Set实例的成员总数 set.size |
keys() | 返回键名的遍历器 |
value() | 返回键值的遍历器 |
entries() | 返回键值对的遍历器 |
forEach() | 使用回调函数遍历每个成员 |
3.练习
数组、字符串去重
//数组去重
const arr = [12, 13, 45, 78, 68, 54, 12, 78, 54]
const s1 = [...new Set(arr)] //转换成集合,然后在数组里展开
console.log(s1)
//字符串去重
const str = "ajdskadjdfks";
const s = [...new Set(str)].join("")
console.log(s)
求交集,并集,差集
// 交集并集和差集
const arr1 = [1, 2, 3, 4, 4, 5, 6];
const arr2 = [2, 7, 8, 9, 3, 4, 2];
// 1.交集,先去重,再判断是否存在
let result = [...new Set(arr1)].filter(item => {
let s2 = new Set(arr2)
if (s2.has(item)) {
return true
} else {
return false
}
});
// 简化:
// let result = [...new Set(arr1)].filter(item => new Set(arr2).has(item))
console.log(result);
//2.并集,先合并,再去重
let return2 = [...new Set([...arr, ...arr2])]
console.log(return2);
//3.差集, 即交集取反
let return3 = [...new Set(arr1)].filter(item => !(new Set(arr2).has(item)))
console.log(return3);
三、weakSet和weakMap集合
WeakMap
1.实例化
let lis = document.getElementsByTagName("li")
let obj = {}
let weakm = new WeakMap()
weakm.set(obj, 'aaa')
WeakMap对象的Key只能是Object实例化的对象或者是派生类的对象,如果不是的话,就会报错;
WeakMap对象的value值可以是任意类型;
2.方法
WeakMap的API用法与Map一样
- has(key):判断是否有 key 关联对象。
- get(key):返回key关联对象(没有则则返回 undefined)。
- set(key,val):设置一组key关联对象。
- delete(key):移除 key 的关联对象。
3.弱键
WeakMap的key只能是object,目的是让这个key被弱持有;
每个键对自己所引用对象的引用都是弱引用,在没有其他引用和该键引用同一对象,这个对象将会被垃圾回收机制清除(相应的key则变成无效的)
4.不可迭代键
WeakMap的key不算是被正式引用,随时可能被回收机制清除掉,因此WeakMap不提供迭代功能
weakSet
1.允许你将弱引用对象储存在一个集合中。
let obj = {
name: 'laila',
age: 18
}
const set = new WeakSet()
set.add(obj)
2.方法
- add(value):在WeakSet 对象中添加一个元素value。
- has(value):判断 WeakSet 对象中是否包含value。
- delete(value):删除元素 value。
3.注意
与WeakMap类似
- WeakSet 只能储存对象引用,不能存放值
- WeakSet 对象中储存的对象值都是被弱引用的
- WeakSet 对象是无法被遍历的