map和set本质是解决object/array键类型受限、顺序不可靠、查删效率低、去重需手写等硬伤的专用结构:map以任意类型为键且保序,set专注存在性判断与自动去重。

直接抓住本质:Map 是带键的容器,Set 是只存值的去重集合。它们共同解决 Object 和 Array 的硬伤——键类型受限、顺序不可靠、查删效率低、去重要手写。
Map 的关键点在哪
重点不是“它能存对象当 key”,而是“它怎么解决你正在写的那段缓存/映射逻辑”:
- 键可以是任意类型(对象、函数、NaN、new Date() 都行),但要注意:两个内容相同但内存地址不同的对象,不视为同一个 key。比如
{id:1}和{id:1}是两个独立 key,不会覆盖 - 插入顺序严格保留,遍历时
for (let [k, v] of map)永远按你set()的顺序来,这点 Object 做不到 -
map.size是真实长度,不用再写Object.keys(obj).length;map.has(key)查找是 O(1),比数组includes()或indexOf()快得多 - 避免用每次新建的值(如
new Date()、/reg/)当 key,除非你明确需要多次记录;若需按内容判等(比如把对象内容当 key),先JSON.stringify(obj)再设,但注意函数、undefined、Symbol 会丢失
Set 的核心就三条
别把它想成“高级数组”,它是为“存在性判断 + 去重”而生的专用结构:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 自动去重靠 SameValueZero 算法:NaN 只存一次,
null和undefined是不同值,两个{a:1}对象仍是两个元素 - 去重最简写法:
[...new Set(arr)]或Array.from(new Set(arr)),比filter((v,i)=>arr.indexOf(v)===i)清晰且快一个数量级 - 判断是否存在用
set.has(val),时间复杂度 O(1);数组得遍历,O(n)。高频检查场景(如权限校验、黑名单过滤)换 Set 能明显降延迟 - Set 本身无键名,只有值;所以
forEach的回调参数是(value, value, set),第二个参数其实是冗余的
什么时候该用 Map 或 Set,而不是 Object / Array
看业务动作,不是看数据长得像不像:
- 你要做“根据用户实例查配置”?→ 用
Map,key 直接放 userObj,不用额外抽 id 字符串 - 你要缓存异步请求结果,key 是 URL + 参数对象?→ 用
Map,序列化参数作 key 更稳;或用 WeakMap(如果 key 是 DOM 元素,且希望不阻止 GC) - 你要从一堆 ID 中快速筛出已加载过的?→ 用
Set存已加载 ID,if (loadedIds.has(id))一行搞定 - 你要合并多个标签列表并去重?→
new Set([...arr1, ...arr2]),比嵌套 filter 干净太多 - 你只是静态配几个字符串映射(如
{'zh': '中文', 'en': 'English'})?→ 还是用 Object,更轻量、可枚举、支持解构
容易忽略但很实用的细节
这些不是冷知识,是上线后帮你少 debug 半小时的关键:
- Map 和 Set 都支持
for...of,也都有keys()、values()、entries()方法,但 Set 的keys()和values()返回的是同一个迭代器(因为没键,值就是键) - Map 的
set()返回自身,支持链式:map.set('a', 1).set('b', 2);Set 的add()同理 - WeakMap / WeakSet 只接受对象作 key / 元素,且不阻止垃圾回收——适合做私有元数据,但不能遍历,也不能用
size - 别用
JSON.stringify(new Set([1,2]))试图序列化 Set,它不会输出内容;要转数组再序列化










