ES6-12-Set Map

数组在JavaScript中的使用正如其他语言的数组一样,但缺少更多类型的集合导致数组也经常被当作队列与栈来使用。
数组只使用了数值型的索引,而如果非数值型的索引是必要的,开发者便会使用非数组的对象。
这种技巧引出了非数组对象的定制实现,即 Set 与 Map。

Set
是一个构造函数
创建:

const s = new Set();
[2, 3, 4, 5, 2, 2].forEach(x => s.add(x));
for (let i of s) {
  console.log(i);
}
//结果会去重

类似数组,值唯一
添加值:add()方法,重复值不会添加
初始化

let set = new Set([1, 2, 3, 4, 4]);
console.log([...set]);
//打印出来是一个数组
let arr = [2, 3, 4, 3, 4, 1, 2];
arr = [...new Set(arr)];//解构赋值,没有...就不是数组
console.log(arr);
//[2, 3, 4, 1]

应用:去重

let items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
console.log(...items);
//1 2 3 4 5 打印出来是数字,与上面相比没有[],所以不是数组去重
let str = "abbcddef";
console.log([...new Set(str)].join(""));
//abcdef 用join连接

两个对象是不同的

let set = new Set();
set.add({});
set.add({});
console.log(set.size);
//长度为2,两个不同的空对象
let a = {};
let b = a;
set.add(a);
set.add(b);
console.log(set.size);
//长度为3,加了两个相同空对象a

向Set实例加入值时不会发生类型转换,5和’5’不同

方法:

add(value),添加值,返回该Set实例的引用。
delete(value),删除值,返回一个布尔值,表示删除是否成功。
has(value),返回一个布尔值,表示该值是否是Set实例的成员。
clear( ),清除所有成员,没有返回值。

let set = new Set();
set.add(1).add(2).add(2);
console.log(set);
//Set(2) {1, 2} 自动去重
console.log(set.has(2));
true//存在
console.log(set.has(3));
false//不存在
set.delete(1);
//Set(1) {2} 删除了1只剩2
set.clear();
//Set(0) {} 删除全部成员为空了

遍历方法:
keys( ),返回键名的遍历器。
values( ),返回键值的遍历器。
由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。

let set = new Set(["red", "green", "blue"]);
for (let item of set.keys()) {
  console.log(item);
}
for (let item of set.values()) {
  console.log(item);
}
//Set结构实例的默认遍历器生成函数就是values()方法
for (let item of set) {
  console.log(item);
}
//以上三种方法全部显示red green blue

entries( ),返回键值对的遍历器。
迭代对象中数组的索引值作为 key, 数组元素作为 value

let set = new Set([98,98,52]);for (let item of set.entries()) {
  console.log(item);
}
[98, 98]    //value值=key值
[52, 52]

forEach( ),使用回调函数遍历每个成员,没有返回值。

let set = new Set([41,58,78]);
set.forEach((value, key, s) => {
  console.log(s.size);
  console.log(value);
});
//3 41 3 58 3 78

结合数组

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}
//map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值
ns = new Set([...ns].filter(x => x % 3 == 0));
console.log(ns);
//Set(1) {6}
//filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
 let a = new Set([1, 2, 3]);
  let b = new Set([4, 3, 2]);
  //并集
  let union = new Set([...a], [...b]);
  console.log(union);
  //Set(3)  {1, 2, 3}
  !!!!!!!!!!!!!!
  //Set([...a], [...b])是错误的,应该是Set([...a,...b]),输出为{1,2,3,4}
  //交集
  let interect = new Set([...a].filter(x => b.has(x)));
  console.log(interect);
  //Set(2) {2, 3}
  //差集
  let diffs = new Set([...a].filter(x => !b.has(x)));
  console.log(diffs);
//Set(1) {1}

WeakSet

WeakSet的成员只能是对象。
WeakSet中的对象都是弱引用。
垃圾回收机制不考虑WeakSet对该对象的引用。
如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占的内存。
WeakSet 不可遍历
《应用场景》
WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息。
只要这些对象在外部消失,它在 WeakSet 里面的引用就会自动消失。

Map

Map类型是键值对的有序列表,而键和值都可以是任意类型。
相较于Object
Object只能用字符串当作键,其他类型作为键时会自动转换为字符串。
字符串-值
Map可以直接使用各种类型的值(包括对象)作为键。
值-值
Object重在表达对象,Map重在表达数据结构–字典。

方法
set(key, value),设置(添加)键值对。
get(key),通过key获取对应值。
类似Set的方法和属性:
has(key)
delete(key)
clear( )
size

let m=new Map();
let o={p:'Hello world'};
m.set(o,'content');
console.log(m.size); //1
console.log(m.get(o)); //content
console.log(m.has(o)); //true
console.log(m.delete(o)); //true
console.log(m.has(o));//false
console.log(m.clear());//undefined

如果Map的键是一个简单类型的值(数值,字符串,布尔值),只要两个值严格相等,Map就认为是同一个键。

 let mm = new Map();mm.set(-0, 123);
  console.log(mm.get(+0));//123
 mm.set(true, 1);
  mm.set("true", 2);
  console.log(mm.get(true));//1
 mm.set(undefined, 3);
  mm.set(null, 4);
  console.log(mm.get(undefined));//3 null==undefined,但是这里要求绝对相等
  map.set(NaN, 111);
  console.log(mm.get(NaN));//第一次是111,第二次是未定义,因为NaN自己都不等于自己,但是作为key的话只能出现一次

遍历方法
Map 结构原生提供三个遍历器生成函数和一个遍历方法。
keys():返回键名的遍历器。
values():返回键值的遍历器。
entries():返回所有成员的遍历器。
forEach():遍历 Map 的所有成员。
Map 结构的默认遍历器接口(Symbol.iterator属性),就是entries方法。

  const map = new Map([
    ["F", "no"],
    ["T", "yes"]
  ]);
  
  for (let [key, value] of map.entries()) {
    console.log(key, value);
  }
  //F no T yes   entries()方法和map的原生遍历方法相同
  for (let [key, value] of map) {
    console.log(key, value);
  }
    //F no T yes

与Set类似,Map也可以利用…(展开运算符)转换为数组,从而利用map( )、filter( )等方法。

  const map0 = new Map()
    .set(1, "a")
    .set(2, "b")
    .set(3, "c");
  console.log(map0);
//Map(3) {1 => "a", 2 => "b", 3 => "c"}
  const map1 = new Map([...map0].filter(([k, v]) => k < 3));
  console.log(map1);
//Map(2) {1 => "a", 2 => "b"}
  const map2 = new Map([...map0].map(([k, v]) => [k * 2, "_" + v]));
  console.log(map2);
 //Map(3) {2 => "_a", 4 => "_b", 6 => "_c"}

与其他数据结构的相互转换
Map转换为数组

  const myMap = new Map().set(true, 7).set({ foo: 3 }, ["abc"]);
  let myArr = [...myMap];
  console.log(myArr);
  //(2) [Array(2), Array(2)]
 //0: (2) [true, 7]
 //1: (2) [{…}, Array(1)]

数组转换为Map

  const myMap = new Map([
    [true, 7],
    [{ foo: 3 }, ["abc"]]
  ]);
  console.log(myMap);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值