Map和Set用于高效处理键值映射与唯一值集合:Map支持任意类型键、插入顺序迭代;Set基于SameValueZero去重,适用于存在性检查与去重场景。

Map 和 Set 不是用来替代对象或数组的,而是解决它们在特定场景下无法高效、准确表达“键值映射”和“唯一值集合”的问题。
Map 适合存“任意类型键 + 顺序敏感”的键值对
普通 Object 的键只能是字符串或 Symbol,且遍历时顺序不保证(实际引擎虽大多按插入顺序,但规范未规定);而 Map 允许任意类型作键(如对象、函数、NaN),且严格按插入顺序迭代。
常见错误现象:obj[{a:1}] = 'x' 实际变成 obj['[object Object]'] = 'x',键被强制转为字符串,多个不同对象会冲突。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 用
Map存以 DOM 元素、React 组件实例、类实例为键的元数据 - 需要频繁增删键值对时,
Map的delete()比delete obj[key]更可靠(后者不触发原型链更新,且无法删除undefined值) - 遍历时优先用
map.forEach()或for (const [key, val] of map),而非Object.keys()+for...in
const m = new Map();
const keyObj = { id: 1 };
m.set(keyObj, 'data for obj');
m.set(NaN, 'nan key'); // ✅ NaN 可作键,且能正确 get
console.log(m.get(keyObj)); // 'data for obj'
console.log(m.get(NaN)); // 'nan key'
Set 专用于去重 + 快速存在性检查
Array 去重要写 [...new Set(arr)] 或用 filter() + indexOf(),低效且不能处理引用类型;Set 内部用哈希实现,add()/has() 平均时间复杂度 O(1),且自动去重。
使用场景:
本文档主要讲述的是j2me3D游戏开发简单教程; 如今,3D图形几乎是任何一部游戏的关键部分,甚至一些应用程序也通过用3D形式来描述信息而获得了成功。如前文中所述,以立即模式和手工编码建立所有的3D对象的方式进行开发速度很慢且很复杂。应用程序中多边形的所有角点必须在数组中独立编码。在JSR 184中,这称为立即模式。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
- 过滤重复请求参数(如多个
fetch请求共用同一组 ID,需去重后批量查) - 记录已处理的事件源(如防止同一按钮连点多次触发)
- 代替布尔标记对象是否“已访问”,避免在对象上挂临时属性污染结构
注意:Set 的去重基于 SameValueZero 算法(类似 ===,但 NaN 与自身相等),所以 new Set([NaN, NaN]) 长度为 1,但 {} 和 {} 仍是两个不同值,不会去重。
const seen = new Set();
const btn = document.getElementById('submit');
btn.addEventListener('click', () => {
if (seen.has(btn)) return;
seen.add(btn);
// 执行提交逻辑
});
性能与内存开销:别为了“时髦”滥用
Map 和 Set 比原生对象/数组略重——它们是集合类结构,有额外的内部哈希表和迭代器支持。如果只是静态配置项(如 { theme: 'dark', lang: 'zh' }),用 Object 更轻量、可压缩、V8 优化更好。
容易踩的坑:
- 把
Map当成“高级对象”到处用,结果调试时发现console.log(map)不显示内容,得用map.entries()或展开符[...map] - 误以为
Set能深比较对象,写set.add({x:1}); set.has({x:1})返回false(因为是不同引用) - 用
Map.prototype.keys()得到的是迭代器,不是数组,不能直接调用.map(),要先转Array.from()或展开
与 JSON 序列化/反序列化的天然隔阂
JSON.stringify() 完全忽略 Map 和 Set,直接返回空对象 {} 或空数组 []。这意味着它们不适合直接作为跨环境数据载体(如 localStorage、fetch body、WebSocket 消息)。
若必须传输,需手动转换:
-
Map→ 数组:用Array.from(map.entries()),反向用new Map(arr) -
Set→ 数组:用[...set],反向用new Set(arr) - 深层嵌套时,得递归处理,或用自定义
toJSON方法(但JSON.stringify不会自动调用它)
这其实是设计使然:Map/Set 是运行时行为结构,不是数据格式。混淆这两者,是很多“为什么存不进 localStorage”的根源。










