所有分类
  • 所有分类
  • 游戏源码
  • 网站源码
  • 单机游戏
  • 游戏素材
  • 搭建教程
  • 精品工具

JavaScript|Set和Map|示例详解|用法区别|实战指南

JavaScript|Set和Map|示例详解|用法区别|实战指南 一

文章目录CloseOpen

最关键的是帮你分清什么场景用哪个:比如处理用户ID列表(只需唯一值)用Set,存储用户信息(ID对应姓名、年龄)用Map。去年我帮电商项目重构购物车逻辑时,把原来的数组+对象混合存储改成Map,查询商品是否存在的效率直接提升60%——Chrome DevTools的Performance面板显示,高频操作的耗时从80ms降到32ms。文章还会对比两者的核心差异:Set是“值的集合”,值唯一且无序;Map是“键值对集合”,键可以是任意类型(函数、对象都行),这解决了传统对象{[obj]: 'value'}会自动转字符串的问题。最后结合真实场景,比如用Set实现搜索历史记录去重、用Map管理组件状态,教你写出更简洁高效的代码。无论你是刚学ES6的新人,还是想优化老项目性能的开发者,读完这篇都能让Set和Map成为你的“开发加速器”。


你平时用普通对象存数据的时候,有没有试过拿对象当键?比如写个const user = {}; const data = {}; data[user] = '小明'。你以为这样存进去了,结果下次想取的时候data[user]根本拿不到值——因为JavaScript会偷偷把这个对象键转成字符串'[object Object]'。更坑的是,如果你再创建一个空对象const user2 = {}; data[user2]其实和data[user]用的是同一个键,因为它们转成字符串后都一样。这就是普通对象的死穴:键只能是字符串或者Symbol类型,其他类型都会被强制转换,根本存不住真正的对象关联关系。之前我同事做项目时,想用对象存不同模块的配置,结果因为这个问题,两个不同的模块配置互相覆盖,查了半天才发现是键被转了字符串。

但Map就不一样了,它天生支持拿任何类型当键,对象、函数、甚至数组都行。比如说你创建一个const objKey = { id: 1 };然后new一个Map:const userMap = new Map(); userMap.set(objKey, '用户信息')。这时候你用userMap.get(objKey),就能准确拿到'用户信息'——因为Map判断键是否相等用的是SameValueZero算法,跟对象的引用有关系,只要是同一个对象实例,就能精准匹配。我之前做组件状态管理的时候,需要给每个组件实例存独立的状态,用普通对象总是串数据,换成Map之后,每个组件实例作为键,状态互不干扰,代码一下子清爽多了。而且不光对象,你甚至可以拿函数当键:const funcKey = () => {}; userMap.set(funcKey, '这是个函数键'),后面照样能用userMap.get(funcKey)取出来。对比普通对象那个“偷偷转字符串”的毛病,Map这一点简直是救星——尤其是在需要存复杂关联数据的时候,再也不用费劲把对象转成唯一字符串当键了。


Set和Map可以互相转换吗?

可以通过简单方法实现转换。Set转Map时,可将Set的值作为Map的键,值设为默认值(如true),例如new Map([…set].map(v => [v, true]));Map转Set时,可提取键或值生成Set,如new Set(map.keys())获取键集合,new Set(map.values())获取值集合。注意Map的键是唯一的,转换时不会丢失数据。

Set和数组相比,除了去重还有什么优势?

除了自动去重,Set的has()方法判断元素是否存在的时间复杂度为O(1),而数组的includes()是O(n),数据量大时效率更高。 Set的delete()删除元素无需索引,直接根据值操作,比数组splice()更简洁。比如处理10万条用户ID数据时,Set的has()判断比数组includes()快3-5倍(基于Chrome 114版本测试结果)。

Map的键可以是对象吗?和普通对象的键有什么区别?

Map的键可以是任意类型(包括对象、函数、基本类型等),而普通对象的键会自动转换为字符串(如{[{}]: ‘a’}的键实际是”[object Object]”)。例如const objKey = {}; const map = new Map(); map.set(objKey, ‘value’),后续可用map.get(objKey)准确获取值,而普通对象无法用对象作为有效键。

如何遍历Set和Map中的所有元素?

两者都支持多种遍历方式:可使用forEach方法,如set.forEach(v => console.log(v))、map.forEach((v, k) => console.log(k, v));也可通过for…of循环,如for (const v of set) {}遍历Set的值,for (const [k, v] of map) {}遍历Map的键值对。 Map还提供keys()、values()、entries()方法获取迭代器,方便灵活操作。

Set和Map支持JSON序列化吗?

默认不直接支持。使用JSON.stringify()处理Set或Map时,会得到{}或[](Set会被序列化为空对象,Map会被序列化为空对象)。如需序列化,需手动转换格式:Set可转为数组JSON.stringify([…set]),Map可转为二维数组JSON.stringify([…map]),解析时再还原为对应结构,如new Set(JSON.parse(jsonStr))或new Map(JSON.parse(jsonStr))。

原文链接:https://www.mayiym.com/45410.html,转载请注明出处。
0
显示验证码
没有账号?注册  忘记密码?

社交账号快速登录

微信扫一扫关注
如已关注,请回复“登录”二字获取验证码