定制设计33.JavaScript映射与集合(Map、Set)数据类型基础知识介绍与使用



文章目录


定制设计映射与集合(Map、Set)

定制设计前文的学习过程中,定制设计我们已经了解了非常多定制设计的数据类型,定制设计包括基础类型、定制设计复杂的对象、定制设计顺序存储的数组等。定制设计为了更好的应对现实生定制设计产中的情况,定制设计我们还需要学习更多的数据类型:映射(Map)和集合(Set)。

映射(Map)

Map是一个键值对定制设计构成的集合,定制设计和对象非常相似,定制设计都是由一个名称对应一定制设计个值组成的。Map定制设计和对象区别在于,Map定制设计的键可以采用任何类型的数据,定制设计而对象只能使用字符串定制设计作为属性名称。

Map定制设计常用的方法

  1. new Map()——创建Map对象;
  2. map.set(key, val)——定制设计添加一个键值对;
  3. map.get(key)——定制设计通过键找到val值,定制设计如果不存在key,返回undefined
  4. map.has(key)——判断map是否存在键key,存在返回true,不存在返回false
  5. map.delete(key)——删除指定键;
  6. map.clear()——清空map中所有的内容;
  7. map.size——map中键值对的数量;

举个例子:

let map = new Map()//创建一个空的Mapmap.set('name','xiaoming')	//字符串作为键map.set(3120181049,'ID')	//数字作为键map.set(true,'Bool')		//bool作为键console.log(map.get('name'))//xiaomingconsole.log(map.has(true))  //trueconsole.log(map.delete(true))//删除true键console.log(map.size)		//2console.log(map.clear())	//清空console.log(map.size)		//0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

代码执行结果:

map.set(key, val)方法返回map本身。

不要使用map[key]访问属性

虽然map[key]方式同样可以访问映射的键值对,但是不推荐使用这种方式,因为它会造成歧义。我们可以看下面的案例:

let map = new Map()map[123] = 123 //创建一个键值对console.log(map[123])//123console.log(map['123'])
  • 1
  • 2
  • 3
  • 4

这里就出现了一个奇怪的结果:

不仅使用键123还可以使用'123'访问数据。

甚至,如果我们使用map.set()map[]混用的方式,会引起程序错误。

JavaScript中,如果我们对映射使用了map[key]=val的方式,引擎就会把map视为plain object,它暗含了对应所有相应的限制(仅支持StringSymbol键)。

所以,我们不要使用map[key]的方式访问Map的属性!!

对象作为Map的键

由于Map对键的类型不做任何限制,我们还可以把对象当作键值使用:

let clazz = {className:'9年1班'}let school = new Map()school.set(clazz,{stu1:'xiaoming',stu2:'xiaohong'})console.log(school.get(clazz))
  • 1
  • 2
  • 3
  • 4

代码执行结果:

在对象中,对象是不能作为属性名称存在的,如果我们把对象作为属性名,也会发生奇怪的事:

let obj = {}let objKey = {key:'key'}obj[objKey] = 'haihaihai'console.log(obj['[object Object]'])
  • 1
  • 2
  • 3
  • 4

代码执行结果:

发生这种现象的原因也非常简单,对象会把非字符串、Symbol类型的属性名转为字符串类型,对象相应的就转为'[object Object]'了,于是对象中就出现了一个名为'[object Object]'的属性。

Map键值比较方法

Map使用SameValueZero算法比较键值是否相等,和===差不多,但是NaNNaN是相等的,所以NaN也可以作为键使用!

链式调用

由于map.set返回值是map本身,我们可以使用如下调用方式:

map.set(1,1)	.set(2,2)	.set(3,3)
  • 1
  • 2
  • 3

与迭代

我们可以在以下三个函数的帮助下完成映射的迭代:

  1. map.keys()——返回map所有键的可迭代对象;
  2. map.values()——返回map所有值的可迭代对象;
  3. map.entries()——返回map所有键值对的可迭代对象;

举个栗子:

let map = new Map([    ['key1',1],    ['key2',2],    ['key3',3],])//遍历所有的键for(let key of map.keys()){    console.log(key)}//遍历所有的值for(let val of map.values()){    console.log(val)}//遍历所有的键值对for(let ky of map.entries()){    console.log(ky)}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

代码执行结果:

遍历的顺序

遍历的顺序和元素插入顺序是相同的,这是和对象的区别之一。

默认的迭代方式

实际上,我们很少使用map.entries()方法遍历Map中的键值对,因为map.entries()map的默认遍历方式,我们可以直接使用如下代码:

let map = new Map([    ['key1',1],    ['key2',2],    ['key3',3],])for(let kv of map){    console.log(kv)}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

代码执行结果:

forEach()

我们还可以通过Map内置的forEach()方法,为每个元素设置一个遍历方法,就像遍历数组一样。

举例如下:

let map = new Map([    ['key1',1],    ['key2',2],    ['key3',3],])map.forEach((val,key,map)=>{    console.log(`${key}-${val}`)})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

代码执行结果:

从数组、对象创建Map

可能童鞋们已经发现了,在上面的案例中,我们使用了一种独特的初始化方式(没有使用set方法):

let map = new Map([    ['key1',1],    ['key2',2],    ['key3',3],])
  • 1
  • 2
  • 3
  • 4
  • 5

我们通过向new Map()传入一个数组,完成了快速的映射创建。

我们还可以通过Object.entires(obj)方法将对象转为数组,该数组的格式和Map需要的格式完全相同。

举个例子:

let obj = {    xiaoming:'heiheihei',    xiaohong:'hahahahah'}let map = new Map(Object.entries(obj))console.log(map)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

代码执行结果:

Object.entries(obj)会返回obj对应的数组:[['xiaoming':'heiheihei'],['xiaoming':'hahahahah']]

从数组、Map创建对象

Object.fromEntries()Object.entries()功能相反,可以把数组和Map转为对象。

let obj = Object.fromEntries([    ['key1','val1'],    ['key2','val2'],    ['key3','val3'],])console.log(obj)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

代码执行结果:

Map转对象:

let map = new Map()map.set('key1','val1')	.set('key2','val2')	.set('key3','val3')let obj = Object.fromEntries(map)console.log(obj)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

代码执行结果:

map.entries()会返回映射对应的键值对数组,我们也可以使用一种稍微麻烦的方式:

let obj = Object.fromEntries(map.entries())
  • 1

以上两种方式作用完全相同,建议选择更为简短的方式。

集合(Set)

Set是一系列值的集合(注意没有键),我们可以简单的把集合看作一个框,什么值都可以直接扔进去,但是每个值都只能出现一次。

常用的方法:

  1. new Set([iter])——创建一个集合,如果传入了一个可迭代变量(例如数组),就使用这个变量初始化集合
  2. set.add(val)——向集合中添加一个元素val
  3. set.delete(val)——删除集合中的val
  4. set.has(val)——判断集合中是否存在val,存在返回true,否则返回false
  5. set.clear()——清空集合中所有的元素
  6. set.size——返回集合中元素的数量

集合使用案例:

let set = new Set()let xiaoming = {name:'xiaoming'}let xiaohong = {name:'xiaohong'}let xiaojunn = {name:'xiaojunn'}set.add(xiaoming)set.add(xiaohong)set.add(xiaojunn)console.log(set)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

代码执行结果:

虽然Set的功能很大程度上可以使用Array代替,但是如果使用arr.find判断元素是否重复,就会造成巨大的性能开销。

所以我们需要在合适的场景使用合适的数据结构,从而保证程序的效率。

集合迭代

集合的迭代非常简单,我们可以使用for...offorEach两种方式:

let set = new Set(['xiaoming','xiaohong','xiaoli'])//使用数组初始化集合for(let val of set){    console.log(val)}set.forEach((val,valAgain,set)=>{    console.log(val)})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

代码执行结果:

注意,使用forEach遍历集合时,和map一样有三个参数,而且第一个和第二个参数完全相同。这么做的目的是兼容Map,我们可以方便的使用集合替换Map而程序不会出错。

Map中使用的方法,Set同样适用:

  1. set.keys()——返回一个包含所有值的可迭代对象
  2. set.values()——返回值和set.keys()完全相同
  3. set.entries()——返回[val,val]可迭代对象

看起啦这些方法有些功能上的重复,很奇怪。实际上,和forEach一样,都是为了和Map兼容。

总结

Map 是一个带键的数据项的集合。

常用方法:

  1. new Map([iter]) —— 创建 map,可选择带有 [key,value] 对的 iterable(例如数组)来进行初始化;
  2. map.set(key, val) —— 根据键存储值,返回 map 自身,可用于链式插入元素;
  3. map.get(key) —— 根据键来返回值,如果 map 中不存在对应的 key,则返回 undefined
  4. map.has(key) —— 如果 key 存在则返回 true,否则返回 false
  5. map.delete(key) —— 删除指定键对应的值,如果在调用时 key 存在,则返回 true,否则返回 false
  6. map.clear() —— 清空 map中所有键值对 ;
  7. map.size —— 返回键值对个数

与普通对象 Object 的不同点主要是任何类型都可以作为键,包括对象、NaN

Set —— 是一组值的集合。

常用方法和属性:

  1. new Set([iter]) —— 创建 set,可选择带有 iterable(例如数组)来进行初始化。
  2. set.add(value) —— 添加一个值(如果 value 存在则不做任何修改),返回 set 本身。
  3. set.delete(value) —— 删除值,如果 value 在这个方法调用的时候存在则返回 true ,否则返回 false
  4. set.has(value) —— 如果 value 在 set 中,返回 true,否则返回 false
  5. set.clear() —— 清空 set。
  6. set.size —— 元素的个数。

MapSet 中迭代总是按照值插入的顺序进行的,所以我们不能说这些集合是无序的,但是我们不能对元素进行重新排序,也不能直接按其编号来获取元素。

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发