Map 和Set(映射和集合)

40 篇文章 1 订阅
39 篇文章 5 订阅

首先看一下面试最经常问的一个问题:介绍下 Set、Map的区别?
应用场景下Set用来数据去重,Map用于数据存储
Set:
1.数据不能重复
2.只存储键值,没有键名,类似于数组
3.可以遍历,方法有add, delete,has
  Map:
   1.数据可以重复
   2.本质上是键值对的集合,类似于集合
   3.可以遍历,可以跟各种数据格式转换,遍历有map.keys,map.values,map.entries();set也有这三个方法
  看完下面内容,不光会对这个问题有更深入的了解,也能更好区分更好使用这两个方法,是前端学习过程中必不可少的

一、Map

Map 是一个带键的数据项的集合,就像一个object 一样,但是他们最大的区别就是 Map 允许任何类型的键(key)
它们的方法和属性如下:

  • new Map() ------创建map。
  • map.set(key,value) -----根据键存储值
  • map.get(key)------根据键来返回值,如果map中不存在对应的 key,则返回 undefined。
  • map.has(key) ------如果key存在则返回true 否则返回 false。
  • map.delete(key) ------清空指定的键值
  • map.clear() ------清空map。
  • map.size() ------返回当前元素个数
let map = new Map();
map.set('1','start');			 //字符串键
map.set(1,'num1'); 			//数字键
map.set(true,'bool1');		//布尔值键
普通的object 会将键转化为字符串,而map 则会保留键的类型,所以下面这两个结果不同
alert(map.get(1)	);			//'num1'		
alert(map.get('1')	);			//'str1'
alert(map.size 	);				//3

Map还可以使用对象作为键

let john={name:"John"};
//存储每个对象的来访次数
let visitsCountMap = new Map();

//John 是map 中的键
visitsCountMap.set(John,123);
alert(visitsCountMap.get(john)	);  //123

链式调用

map.set('1', 'str1')
  .set(1, 'num1')
  .set(true, 'bool1');

Map迭代
如果要在map 里使用循环,可以用下面三个方法:
map.keys() ------遍历并返回所有的键
map.values() ------遍历并返回所有的值
map.entries() ------遍历并返回所有的实体([key,value],for…of 在默认情况下使用的就是这个)

let recipeMap = new Map([
  ['cucumber', 500],
  ['tomatoes', 350],
  ['onion',    50]
]);

// 遍历所有的键(vegetables)
for (let vegetable of recipeMap.keys()) {
  alert(vegetable); // cucumber, tomatoes, onion
}

// 遍历所有的值(amounts)
for (let amount of recipeMap.values()) {
  alert(amount); // 500, 350, 50
}

// 遍历所有的实体 [key, value]
for (let entry of recipeMap) { // 与 recipeMap.entries() 相同
  alert(entry); // cucumber,500 (and so on)
}

迭代的顺序与插入值的顺序相同,与普通的object不同,Map保留了此顺序。
除此之外,Map 有内建的 forEach 方法,与 Array 类似:
// 对每个键值对 (key, value) 运行 forEach 函数

recipeMap.forEach( (value, key, map) => {
  alert(`${key}: ${value}`); // cucumber: 500 etc
});

Object.entries:从对象创建 Map
当创建一个 Map后,我们可以传入一个带有键值对的数组(或其他可迭代的对象)来进行初始化,如下所示:

// 键值对 [key, value] 数组
let map = new Map([
  ['1',  'str1'],
  [1,    'num1'],
  [true, 'bool1']
]);

alert( map.get('1') ); // str1

如果我们想从一个已有的普通对象来创建一个 Map,那么我们可以内建方法,Object.entries(obj),该方法返回对象的键/值对数组,该数组格式完全按照Map所需的格式。

let obj = {
  name: "John",
  age: 30
};
alert(Object.entries(obj) instanceof Array) //true,由此可以验证该方法返回的类型是数组
let map = new Map(Object.entries(obj));  

alert( map.get('name') ); // John

这里,Object.entries 返回键/值对数组:[[“name”,“John”],[“age”,30] ].这就是Map所需要的格式。

Object.fromEntries:从Map创建对象
我们刚刚已经学习了如何使用 Object.entries(obj) 从普通对象 创建 Map
Object.fromEntries方法作用是相反的:给定一个具有 [key,value] 键值对的数组,它会根据给定数组创建一个对象

let prices = Object.fromEntries([
  ['banana', 1],
  ['orange', 2],
  ['meat', 4]
]);

// 现在 prices = { banana: 1, orange: 2, meat: 4 }

alert(prices.orange); // 2

我们可以使用Object.fromEntries 从Map 得到一个普通对象
例如,我们在Map 中存储了一些数据,但是我们需要把这些数据传给普通对象的第三方代码

let map = new Map();
map.set('banana', 1);
map.set('orange', 2);
map.set('meat', 4);
//*
let obj = Object.fromEntries(map.entries()); // 创建一个普通对象(plain object)(*)

// 完成了!
// obj = { banana: 1, orange: 2, meat: 4 }

alert(obj.orange); // 2

调用 map.entries() 将会返回一个可迭代的键/值 对,这刚好是 Object.fromaEntries 所需要的格式
我们可以把 * 下面这行写的更短

let obj = Object.fromEntries(map); // 省掉 .entries()

最后的作用是一样的,因为Object.fromEntries 期望得到一个可迭代的对象作为参数,而不一定是数组,并且map 的标准迭代会返回跟 map.entries() 一样的键/值 对。因此,我们可以获得一个普通对象,其键/值 对与 map相同

二、Set

set 是一个特殊的类型集合------“值的集合(没有键)”,它的每一个值只能出现一次
主要方法有

  • new Set(iterable) ------创建了一个set,如果提供了一个iterable对象值(通常是数组),将会从数组里面复制值到 set 中。
  • set.add(value) ------添加一个值,并返回set 本身
  • set.delete(value) ------删除值,如果value 这个方法调用的时候存在则返回true,否则返回false。
  • set.has(value) ------如果 value 在set中,返回true,否则返回false
  • set.clear()------清空set。
  • set.size ------返回元素个数。
    它主要特点是,重复使用同一个值调用 set.add(value)并不会发生什么改变,这就是 Set 里面的每一个值只出现一次的原因。
    比如,我们有客人来访,我们想记住他们每一个人,但是已经来访过的客人再次来访,不应造成重复记录,每个访客必须只被“计数”一次。
    Set 可以帮助我们解决这个问题:
let set = new Set();

let john = { name: "John" };
let pete = { name: "Pete" };
let mary = { name: "Mary" };

// visits,一些访客来访好几次
set.add(john);
set.add(pete);
set.add(mary);
set.add(john);
set.add(mary);

// set 只保留不重复的值
alert( set.size ); // 3

for (let user of set) {
  alert(user.name); // John(然后 Pete 和 Mary)
}

Set 迭代
我们可以使用 for…of 或 forEach 来遍历 Set:

let set = new Set(["oranges", "apples", "bananas"]);

for (let value of set) alert(value);

// 与 forEach 相同:
set.forEach((value, valueAgain, set) => {
  alert(value);
});

forEach 的回调函数有三个参数:一个value,然后是 同一个值 valueAgain,最后是目标对象。没错,同一个值在参数里出现了两次。
forEach 的回调函数有三个参数,是为了与 Map 兼容。
Map中用于迭代的方法在 Set中也同样支持:

  • set.keys() —— 遍历并返回所有的值(returns an iterable object for values),
  • set.values() —— 与 set.keys() 作用相同,这是为了兼容 Map,
  • set.entries() ——遍历并返回所有的实体(returns an iterable object for entries)[value,
    value],它的存在也是为了兼容 Map。
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值