• 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()//创建一个空的Map
    map.set('name','xiaoming')	//字符串作为键
    map.set(3120181049,'ID')	//数字作为键
    map.set(true,'Bool')		//bool作为键
    
    console.log(map.get('name'))//xiaoming
    console.log(map.has(true))  //true
    console.log(map.delete(true))//删除true键
    console.log(map.size)		//2
    console.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])//123
    console.log(map['123'])
    
    • 1
    • 2
    • 3
    • 4

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

    image-20220610213719690

    不仅使用键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

    代码执行结果:

    image-20220610215432261

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

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

    代码执行结果:

    image-20220610215731673

    发生这种现象的原因也非常简单,对象会把非字符串、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

    Map的遍历与迭代

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

    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

    代码执行结果:

    image-20220611202407661

    遍历的顺序

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

    默认的迭代方式

    实际上,我们很少使用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

    代码执行结果:

    image-20220611203140858

    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

    代码执行结果:

    image-20220611203643650

    从数组、对象创建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

    代码执行结果:

    image-20220611205622630

    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

    代码执行结果:

    image-20220611210835380

    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

    代码执行结果:

    image-20220611211125496

    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

    代码执行结果:

    image-20220611212417105

    虽然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

    代码执行结果:

    image-20220611212802952

    注意,使用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 中迭代总是按照值插入的顺序进行的,所以我们不能说这些集合是无序的,但是我们不能对元素进行重新排序,也不能直接按其编号来获取元素。

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    JAVA小说小程序系统是怎样开发的
    Vue语法模板续篇
    16.The Tensor Product:Vector/Covector combinations
    JAVA设计模式详解(独家AI解析)
    在echaerts中渲染50万条数据的优化方案
    【Swift 60秒】13 - Dictionaries
    Flutter 列表组件ListView 网格布局组件GridView
    创意作品管理软件 Bridge 2024 mac中文版 br2024功能特色
    丹青映画携梦枕貘巨著《暗狩之师》参加玩协四展
    Android仿QQ消息拖拽效果(一)(二阶贝塞尔曲线使用)
  • 原文地址:https://blog.csdn.net/hjseo_seg/article/details/126097754