Set对象和Map对象

前言

JavaScript的默认对象表示方式{}可以视为其他语言中的Map或Dictionary的数据结构,即一组键值对。
但是JavaScript的对象有个小问题,就是键必须是字符串。但实际上Number或者其他数据类型作为键也是非常合理的。
为了解决这个问题,最新的ES6规范引入了新的数据类型Map

以上摘抄自雪峰老师的教程

Map

Map是一组键值对的结构,具有极快的查找速度,且内部的key(键)是唯一的

const user = {
	age: 26,
	name: 'haonan'
}

let map = new Map();
map.set(user, 'henry'); //增加(存在则更新)一个map键值对
map.set(12, 'type is number')
console.log(map.get(user)) //获取user对应的值
console.log(map.get(12))
console.log(map)
map.delete(12) //删除key为12的键值对
console.log(map.size) //查询map的键值对数量
console.log(map.has(user)) //查询是否包含user这个key

map.clear() //清空map的键值对
console.log(map.size)

map.set(NaN, '特殊的1')
map.set(NaN, '特殊的2'); //会覆盖以前的key为NaN的值,map内部NaN与NaN之间是指向同一个对象的
console.log(map)

要注意的是:

  • 由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉;
  • NaN在Map内部也认为是同一个key

Set

SetMap类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set中,没有重复的key。

let st = new Set();

const user = {
	name: 'henry',
	qq: '123456'
}
st.add(user).add(user); //添加一个新的key,add后返回set对象本身,所以可以链式添加
console.log('size', st.size) //查询Set中key的数量
let bool = st.delete(user) //删除key,放回是否有删除成功(false说明是不存在)
console.log('bool', bool)

st.add(11)
console.log('has', st.has(11)) //查询是否存在这个key

st.clear(); //清空Set对象的所有key
console.log('size', st.size)

console.log(NaN === NaN); //false
let st1 = new Set([NaN, NaN, NaN]);
console.log(st1); //Set {NaN},虽然NaN不等于NaN,但是在set内部默认是同一个元素

NaN在Set内部也认为是同一个key

应用场景

我们知道了MapSet的大概用法,那平时应该怎么用呢?

先来说说Set,它的最大用法是可以去除数组中的重复元素

let arr = [1, 2, '1', '2', 2, '1'];

let st = new Set(arr);

console.log('st', st);
//Array.from转化类数组对象为数组
console.log('st array', Array.from(st));
//打印出:st array [ 1, 2, '1', '2' ]

那再来说说Map,它的特点有:

  1. key可以是任意类型,不像Object,key值只能是String类型;
  2. 组键值对的结构,具有极快的查找速度;
  3. key是唯一的,不可重复的;

根据这些特点,它可以应用在以下场景:

//统计元素出现的次数并打印出来
const user1 = {
	name: 'henry',
	age: 26
};
const user2 = {
	name: 'jamie',
	age: 24
}
const arr = [user2, 2, user1, 3, 5, 4, 'jamie', 8, 6, 4, user1, 9, 5, 1, 3, 5, 4, user2, 8, 6, 5, 4, user1, 2, 1, 2,
	'henry'
];

const map = new Map()
for (let value of arr) {
	const num = map.get(value)
	map.set(value, (num || 0) + 1)
}
for (let [key, value] of [...map]) {
	console.log(key, `出现次数:${value}次`)
}

上面的数组的元素还可以是一些页面的DOM节点之类的,数组的元素可以很多,Map的出现大大增加了查询的效率和统计方便

遍历以及keys,values,entries的用法

遍历的方法可以看我这篇文章,这里只讲解用for…of来遍历

for…of的遍历其实就是利用对象内部的Symbol.iterator这个方法,那我们就来对比一下keys,values,entries和Symbol.iterator是不是同一个方法

//数组
let arr = [1, 2, 3];
console.log(arr.keys === arr[Symbol.iterator])
console.log(arr.values === arr[Symbol.iterator])
console.log(arr.entries === arr[Symbol.iterator])
//结果:false true false

//Set
let st = new Set(['11', 22, 33]);
console.log(st.keys === st[Symbol.iterator])
console.log(st.values === st[Symbol.iterator])
console.log(st.entries === st[Symbol.iterator])
// 结果:true true false

//Map
let map = new Map([
	['name', 'henry'],
	['qq', '123456'],
	['sex', 'male']
])
console.log(map.keys === map[Symbol.iterator])
console.log(map.values === map[Symbol.iterator])
console.log(map.entries === map[Symbol.iterator])
// 结果:false false true

由此我们可以知道for (let item of list) { console.log('item ', item ) }中的item在对Array中对应的value值,在Set中对应的key值(因为Set其实没有value值),在Map中对应entries(即整个键值对本身);

可以用下面的代码验证一下:

let list = [1, 2, 3];
list = new Set(list);//控制注释掉来分别验证
// list = new Map([
// 	['name', 'henry'],
// 	['qq', '123456'],
// 	['sex', 'male']
// ])

let keysI = list.keys();
for (let k of keysI) {
	console.log('k', k)
}

let valuesI = list.values();
for (let v of valuesI) {
	console.log('v', v)
}

let entriesI = list.entries();
for (let e of entriesI) {
	console.log('e', e)
}

for (let o of list) {
	console.log('o', o)
}

另外Map的遍历还可以用forEach

let map = new Map([
	['name', 'henry'],
	['qq', '123456']
])

map.forEach(function(value, key) {
	console.log(key, value)
})
//打印出:
//name henry
//qq 123456

注意forEach第一个值是value,第二个值才是key

最后,来一个很常见的面试题:

//统计数字出现的次数并按照从小到大打印出来
const arr = [1, 2, 3, 3, 5, 4, 8, 6, 4, 2, 9, 5, 1, 3, 5, 4, 7, 8, 6, 5, 4, 5, 2, 1, 2];

实现的代码:

const map = new Map()
for (let value of arr) {
	const num = map.get(value)
	map.set(value, (num || 0) + 1)
}
const list = [...map].sort(function([key1, value1], [key2, value2]) {
	return key1 - key2
})
// console.log(list)
for (let [key, value] of list) {
	console.log(`数字${key}出现次数:${value}次`)
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值