一、Set
ES6中新增的Set是一种新集合类型,Set在很多方面都像是加强的Map,类似于数组,但是Set中不能存放重复的值
创建set
Set本身也是一个构造函数,因此可以通过new来生成Set实例,Set函数可以接受一个数组(或具有Iterable接口的其他数据结构)作为参数,来初始化Set实例
{
let set = new Set([1,2,3,4,5]);
for(let v of set){
console.log(set); // 1 2 3 4 5
}
console.log([...set]); // [1,2,3,4,5]
}
{
// set可以去掉数组中重复的值
let items = new Set([1,2,3,5,4,6,8,1,3]);
console.log([...items]); // [1,2,3,5,4,6,8]
// 去掉字符串中重复字符
let str = 'aabbccdd';
console.log([...new Set(str)].join("")); // abcd
}
set的属性与方法
属性:
- constructor:构造函数,默认就是Set函数
- size:返回Set实例的成员数量
方法
- 操作方法,用于操作数据
- add(value):添加值,返回该Set实例的引用
- delete(value):删除值,返回一个布尔值,表示删除是否成功
- has(value):返回一个布尔值,表示该值是否是Set实例的成员
- clear():清楚所有成员,没有返回值
- 遍历方法,用于遍历成员
- keys():返回键名的遍历器
- values():返回键值的遍历器(因为Set结构没有键名,只有键值,因此keys方法和values方法完全一致)
- entries():返回键值对的遍历器
- forEach():使用回调函数遍历每个成员,没有返回值
{
let set = new Set();
set.add(1).add(2).add(3);
console.log(set); // Set(3) {1, 2, 3}
console.log(set.has(2)); // true
console.log(set.has(3)); // true
}
{
// 遍历方法
let set = new Set(['red','blue','green']);
for (const item of set.keys()) {
console.log(item); // red blue green
}
for (const item of set.values()) {
console.log(item); // 与上面一样
}
for (const item of set.entries()) {
console.log(item); // [ 'red', 'red' ] [ 'blue', 'blue' ] [ 'green', 'green' ]
}
set.forEach((item) => console.log(item.toUpperCase())) // RED BLUE GREEN
set.forEach((item,key,set) => {
console.log(set.size); // 3
})
}
set遍历的应用
扩展运算符和Set结构相结合,就可以去除数组的重复成员
{
let arr = [2,3,54,4,3,2,4];
arr = [...new Set(arr)];
console.log(arr); // [ 2, 3, 54, 4 ]
}
Set实例可以间接的使用数组的map和filter方法
{
let ns = new Set([1,2,3,4]);
ns = new Set([...ns].map(x => x * 2));
console.log(ns); // Set(4) { 2, 4, 6, 8 }
ns = new Set([...ns].filter(x => x > 2));
console.log(ns); // Set(3) { 4, 6, 8 }
}
扩展运算符、map、filter和Set结构相结合实现并集、交集、差集
{
let a = new Set([1,2,3]);
let b = new Set([2,3,4]);
// 并集
let union = new Set([...a],[...b]);
console.log(union); // Set(3) { 1, 2, 3 }
// 交集
let cross = new Set([...a].filter(x => b.has(x)));
console.log(cross); // Set(2) { 2, 3 }
// 差集
let diff = new Set([...a].filter(x => !b.has(x)));
console.log(diff); // Set(1) { 1 }
}
set垃圾回收机制
引用类型的数据如果没有使用了,那么就会被系统的垃圾回收机制回收掉
{
let = obj = {name:"Tom"};
let newObj = obj;
obj = null;
console.log(newObj); // {name:"Tom"}还有,因为还在使用
newObj = null;
console.log(newObj); // null没有了
}
WeakSet
WeakSet与Set的区别
- WeakSet的成员只能是对象
- WeakSet中的对象都是弱引用
- 垃圾回收机制不考虑WeakSet对该对象的引用
- 如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收对象所占用的内存
- 应用场景
- WeakSet适合临时存放一组对象,以及存放跟对象绑定的信息
- 只要这些对象在外部消失,它在WeakSet里面的引用就会自动消失
- ES6规定WeakSet不可遍历
在这里插入代码片
二、Map
Map类型是键值对的有序列表,而键和值都可以是任意类型
相较于Object
- Object只能用字符串当做键,其他类型作为键会自动转换为字符串,相当于字符串-值
- Map可以直接使用各种类型的值(包括对象)作为键
- Object重在表达对象,Map重在表达数据结构-字典
Map的基本用法
- set(key,value):设置键值对
- get(key):通过key获取对应的值
- 类似Set的方法和属性:has(key)、delete(key)、clear()、size
{
let map = new Map();
map.set("name","Tom");
map.set({},"Object");
map.set(function(){},"func");
console.log(map);
}
Map构造函数可以接收一个数组作为参数,该数组的成员是一组表示键值对的数组
{
let map = new Map([['one','tow'],['hello',"world"]]) //有多少个数组就有多少个数组里面的键值对
console.log(map); // 数组的第一个元素为key,第二个元素为value Map(2) { 'one' => 'tow', 'hello' => 'world' }
}
不仅仅是数组,任何具有Iterator接口、且每个成员都是一个双元素的数组的数据结构都可以作为Map构造函数的参数。
只有对同一个对象的引用,Map才会认为是同一个键,Map的键实际上是和内存地址绑定的,只要内存地址不一样,就是两个键。
{
const mm = new Map();
mm.set(["a"], 5);
console.log(mm.get(["a"])); // undefined,不是同一个引用,因此获取不到
const k1 = {};
const k2 = {};
mm.set(k1, 100);
mm.set(k2, 200);
console.log(mm.get(k1), mm.get(k2)); // 同一个引用,100 200
}
如果Map的键是一个简单类型的值(布尔、字符串、数值)只要两个值严格相等,那么Map就认为是同一个键
遍历方法
Map结构原生提供三个遍历器生成函数和一个遍历方法
- keys():返回键名的遍历器
- values():返回键值的遍历器
- entries():返回键值对的遍历器
- forEach():使用回调函数遍历每个成员,没有返回值
- Map结构的默认遍历器接口(Symbol.iterator属性)就是entries方法
{
let map = new Map();
map.set('name','tom').set('age',20);
console.log(map);
for (const iterator of map) {
console.log(iterator); // [ 'name', 'tom' ] [ 'age', 20 ]
}
for (const iterator of map.entries()) {
console.log(iterator); // 与上面一样
}
}
{
// 与Set一样,Map也可以利用扩展运算符转换为数组,从而使用数组的方法
let map = new Map();
map.set('a',100).set('b',200).set('c',300);
console.log(map); // Map(3) { 'a' => 100, 'b' => 200, 'c' => 300 }
let map1 = new Map([...map].filter(([k,v]) => v > 100));
console.log(map1); // Map(2) { 'b' => 200, 'c' => 300 }
}
与其他数据结构的相互转换
Map转换为数组
{
let map = new Map().set('a',100).set('b',200);
console.log([...map]);
// 数组转为Map
let myMap = new Map([['a',1],[{b:'1'},2]]);
console.log(myMap); // Map(2) { 'a' => 1, { b: '1' } => 2 }
}
WeakMap
WeakMap与Map的区别
- WeakMap只接受对象作为键名(null)除外,不接受其他类型的值作为键名
- WeakMap的键名所指向的对象,不会计入垃圾回收机制