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

news2024/11/17 21:27:34

在这里插入图片描述


在这里插入图片描述


文章目录

  • 映射与集合(Map、Set)
    • 映射(Map)
      • Map常用的方法
      • 不要使用map[key]访问属性
      • 对象作为Map的键
      • Map的遍历与迭代
        • 默认的迭代方式
        • forEach()
      • 从数组、对象创建Map
      • 从数组、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

代码执行结果:

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'])

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

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))

代码执行结果:

image-20220610215432261

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

let obj = {}
let objKey = {key:'key'}
obj[objKey] = 'haihaihai'
console.log(obj['[object Object]'])

代码执行结果:

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)

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)
}

代码执行结果:

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)
}

代码执行结果:

image-20220611203140858

forEach()

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

举例如下:

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

代码执行结果:

image-20220611203643650

从数组、对象创建Map

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

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

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

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

举个例子:

let obj = {
    xiaoming:'heiheihei',
    xiaohong:'hahahahah'
}
let map = new Map(Object.entries(obj))
console.log(map)

代码执行结果:

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)

代码执行结果:

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)

代码执行结果:

image-20220611211125496

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

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

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

集合(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)

代码执行结果:

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)
})

代码执行结果:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/409727.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vuex 之一:3种拿到 state 中数据的方式与实例剖析

Ⅰ、Vuex 简介: 1、Vuex 是什么? 答:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式; 而所谓状态就是指:组件中所维护的数据); (简而言之:就是状态管理,解决复杂组件数据通信&#xff0c…

React中实现keepalive组件缓存效果

背景:由于react官方并没有提供缓存组件相关的api(类似vue中的keepalive),在某些场景,会使得页面交互性变的很差,比如在有搜索条件的表格页面,点击某一条数据跳转到详情页面,再返回表…

处理vue中的长按事件、点击事件、默认事件冲突

写在前面 示例是h5项目。技术栈:vue vant nuxt。 知识点简介: touchstart: // 手指放到屏幕上时触发 touchend: // 手指离开屏幕时触发 touchmove: // 手指在屏幕上滑动式触发 touchcancel: // 系统取消touch事件的时候触发 页面及需求: …

一文教会你何为重绘、回流?

文章目录css图层图层创建的条件重绘(Repaint)回流触发重绘的属性触发回流的属性常见的触发回流的操作优化方案requestAnimationFrame----请求动画帧写在最后学习目标: 了解前端Dom代码、css样式、js逻辑代码到浏览器展现过程了解什么是图层了解重绘与回流了解前端层…

【已失效】免翻在Chrome上使用新必应(New Bing)聊天机器人

已失效,暂时没时间去摸索,大家可以在评论区讨论,其实大家评论的我也尝试过了,并没有找到一个很完美的方式,有时间折腾再更新吧!! 这里不讲如何加入New Bing内测 文章目录【更新】免翻使用New B…

如何理解虚拟DOM

一、js 操作DOM 假如现在你需要写一个像下面一样的表格的应用程序,这个表格可以根据不同的字段进行升序或者降序的展示。 这个应用程序看起来很简单,你可以想出好几种不同的方式来写。最容易想到的可能是,在你的 JavaScript 代码里面存储这样…

【CSS重点知识】属性计算的过程

✍️ 作者简介: 前端新手学习中。 💂 作者主页: 作者主页查看更多前端教学 🎓 专栏分享:css重难点教学 Node.js教学 从头开始学习 ajax学习 标题什么是计算机属性确定声明值层叠冲突继承使用默认值总结什么是计算机属性 CSS属性值的计算…

Vue实例生命周期

Vue实例的生命周期就是Vue实例从创建到销毁的全过程。在这个过程中,经历了创建、初始化数据、编译模板、挂载Dom(beforeCreate(){}、created(){}、beforeMount(){}、mounted(){})、渲染→更新→渲染(beforeUpdate(){}、updated(){})、卸载(beforeDestroy(){}、destr…

SVG+CSS动画实现动效(流光、呼吸等效果)

流光效果 绘制流光线条 创建SVG,根据UI给的背景图,定位到图上每条管道(即流光线条的路径)的起始点以及拐点,绘制折线。绘制折线的时候按照下图方框通过class分组,这几组的光线流动是同时出发的。 svg相关知…

【大学生期末大作业】HTML+CSS+JavaScript — 模仿博客网站设计(Web)

你为什么不亲自下船, 就一次也好啊, 亲眼去看看这个世界。 目录 你为什么不亲自下船, 就一次也好啊, 亲眼去看看这个世界。 关于HTML5: 关于CSS: 关于JavaScript: 一、🌎前言…

牛客前端刷题(四)——微信小程序篇

还在担心面试不通过吗?给大家推荐一个超级好用的刷面试题神器:牛客网,里面涵盖了各个领域的面试题库,还有大厂真题哦! 赶快悄悄的努力起来吧,不苒在这里衷心祝愿各位大佬都能顺利通过面试。 面试专栏分享,感觉有用的小伙伴可以点个订阅,不定时更新相关面试题:面试专栏…

Vue 使用 Vue-socket.io 实现即时聊天应用(Vue3连接原理分析)

目录 前言: 一、新建 Vue3 项目 二、下载相关依赖 2.1 后台服务 2.2 前端连接 2.3 启动项目 2.4 触发与接收事件 2.5 原因分析 三、vue3 使用socket的原理 3.1 socket对象实例 3.2 socket 触发事件 3.3 socket对象监听原生事件 3.4 vue-socket.io 源码解析 …

宝塔面板安装部署Vue项目,Vue项目从打包到上线

前期准备 1.宝塔面板已经成功安装到服务器 2.vue项目已经成功开发完成 开始 在宝塔面板中选择PHP项目添加站点,站点PHP版本设置为纯静态,输入域名或者IP 这是后你会获得一个网站文件目录 点击根目录进入目录后,若你的Vue项目么有打包好需…

可视化大屏的几种屏幕适配方案,总有一种是你需要的

假设我们正在开发一个可视化拖拽的搭建平台,可以拖拽生成工作台或可视化大屏,或者直接就是开发一个大屏,首先必须要考虑的一个问题就是页面如何适应屏幕,因为我们在搭建或开发时一般都会基于一个固定的宽高,但是实际的…

海康摄像头web无插件3.2,vue开发,Nginx代理IIS服务器

在vue中实现海康摄像头播放,采用海康web无插件3.2开发包,采用Nginx代理IIS服务器实现; 1 摄像头要求,支持websocket 2 Nginx反向代理的结构 3 vue前端显示视频流代码 参考地址: https://blog.csdn.net/Vslong/artic…

【Vue全家桶】新一代的状态管理--Pinia

🍳作者:贤蛋大眼萌,一名很普通但不想普通的程序媛\color{#FF0000}{贤蛋 大眼萌 ,一名很普通但不想普通的程序媛}贤蛋大眼萌,一名很普通但不想普通的程序媛🤳 🙊语录:多一些不为什么的…

【微信小程序】一文带你了解数据绑定、事件绑定以及事件传参、数据同步

🐚作者简介:苏凉(专注于网络爬虫,数据分析,正在学习前端的路上) 🐳博客主页:苏凉.py的博客 🌐系列专栏:小程序开发基础教程 👑名言警句&#xff1…

项目完成后的打包流程(超级详细)

* 打包: * 将多个文件压缩合并成一个文件 * 语法降级 * less sass ts 语法解析, 解析成css * .... * 打包后,可以生成,浏览器能够直接运行的网页 > 就是需要上线的源码! 最简单的打包流程: 首先我们项目…

vue项目实现前端预览word和pdf格式文件

最近做vue项目遇到一个需求,就是前端实现上传word或pdf文件后,后端返回文件对应的文件流,前端需要在页面上展示出来。word预览简单一些,pdf预览我试过pdfjs,vue-pdf总是报各种奇奇怪怪的bug,但最终总算解决了问题,先看…

HttpServletResponse 类

a)HttpServletResponse 类的作用 HttpServletResponse 类和 HttpServletRequest 类一样。每次请求进来,Tomcat 服务器都会创建一个 Response 对象传 递给 Servlet 程序去使用。HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应…