Map和Set是ES6为弥补对象与数组缺陷而设计的原生集合类型,语义准确、行为稳定、性能可预期:Map支持任意类型键且保持插入顺序,size为O(1);Set去重与存在性判断均为O(1),适合高频更新场景。

Map 和 Set 是 ES6 引入的原生集合类型,不是语法糖,而是为解决对象和数组在特定场景下的硬伤而设计的。它们强不在“功能多”,而在“语义准、行为稳、性能可预期”。
Map 比普通对象更可靠
普通对象本质是属性容器,不是数据结构。Map 才是专为键值映射设计的工具:
-
键类型无限制:对象会把非字符串键(比如
{id: 1}、undefined、数字42)自动转成字符串,导致{id: 1}和{name: 'a'}都变成"[object Object]",键冲突;Map 允许任意值作键,且只对同一引用判等。 -
插入顺序严格保留:Object 的枚举顺序在 ES2015 后虽也按插入顺序,但仅限字符串和 Symbol 键;Map 对所有键类型都保证顺序,遍历
for (const [k, v] of map)总是稳定可靠。 -
操作开销可控:获取长度用
map.size是 O(1);对象得靠Object.keys(obj).length,每次都要生成新数组。频繁增删时,Map 底层哈希实现比对象属性动态分配更轻量。
Set 比数组去重更高效
用数组模拟集合,本质是“用线性结构扛哈希需求”,容易掉坑:
-
去重逻辑自动完成:数组去重要写
filter((v, i) => arr.indexOf(v) === i)或嵌套循环,时间复杂度 O(n²);Set 构造时就去重:new Set([1, 1, 2])直接得{1, 2},O(n) 一次过。 -
存在性判断快得多:查某 ID 是否已存在,数组用
arr.includes(id)是 O(n);Set 用set.has(id)是平均 O(1),尤其在几千个元素以上差距明显。 -
不干扰原始数据结构:数组的
push/splice会改变索引,Set 的add/delete不涉及位移,适合高频更新的集合(如实时在线用户列表、已读消息 ID 缓存)。
什么时候不该换?
不是所有场景都适合上 Map/Set:
立即学习“Java免费学习笔记(深入)”;
- 静态配置项(如
{ theme: 'dark', lang: 'zh' }),对象更简洁,可直接解构、点访问、JSON 序列化。 - 需要稀疏索引或数值下标随机访问(如
arr[100000] = 'x'),数组仍是唯一选择;Set 和 Map 不支持下标寻址。 - 只读小集合(
真正体现优势的,是那些“数据动态变化+需高频查找+键类型复杂”的场景——比如用 DOM 元素作键缓存计算结果(Map)、用用户 ID 实时维护已选状态(Set)。这时候,不是“能用”,而是“该用”。(资料截至 2025 年 12 月)











