Skip to content

JS 为什么新增 Set 与 Map

提示

Map / Set 是为弥补 普通对象与数组 在「键类型、唯一性、有序性、性能」上的短板;不必机械地把 Map 当「替代 Object」、Set 当「替代 Array」——前者是映射与字典场景,后者是集合与去重场景,语义更清晰。

要点速览

shell
ES6 之前常驻结构主要是「对象(键值)」与「数组(有序列表)」,各有局限。

# Map —— 为何要它
对象的键在非 Symbol 时被当作字符串语义处理;枚举顺序与原型链也会增加心智负担;
Map:任意类型作键(含对象)、插入顺序稳定、自带 size、无「继承来的默认键」,适合词典与缓存索引。

# Set —— 为何要它
数组允许重复元素,大批量下去重(Array Set)成本高;仅靠 includes 判断是否「出现过」近似 O(n)
Set:值唯一、has 近似 O(1),适合标签集合、黑名单、瞬时去重。

# 心智模型
业务配置、JSON 形态的普通数据:仍常用 Object;
需要「非标量键」「稳定迭代顺序」「频繁增删键」:优先考虑 Map;
需要「不允许重复」「集合运算」、且要**反复判断成员是否存在**:优先考虑 Set;
仍要按索引随机访问序列:仍旧是 Array。

相较 Object / Array 的补充对照(承接《优化》篇详解)

Map 相对 Object

shell
键类型:对象键实际是 String / Symbol(其它类型会先转字符串);Map 可为任意引用或原始值。
有序性:Object 在现代引擎下键顺序有一套规则但并非为「词典」建模;Map 始终按插入序迭代。
体量:巨型键集合下频繁删改 Map 常见实现往往更友好;小配置 Object 仍足够简单。

Set 相对 Array

shell
唯一性:Set 自动维护不重复;数组需逻辑或二次结构保证。
查找:大范围下 has 优于反复 includes/sccan。
交集 / 差集:用 Set 表达集合运算往往更直白(也可转回数组输出)。

对照表(速记)

shell
结构     本质 / 值类型                      是否允许重复          键是否有序    长度获取                       查询性能         是否继承原型    迭代方式
Object  普通业务对象    键只能:字符串/Symbol            值可重复,键唯一        ES6 后有序   Object.keys().length         一般             有原型污染风险   for/in
Map     键值映射      键任意类型                      值可重复,键唯一       插入有序      .size O(1)                  哈希快            纯净无原型      for/of、forEach
Array   有序序列      下标                            元素可任意重复         下标有序      .length、includes O(n)        线性扫描为主              for/of、forEach
Set     唯一集合      仅存值                           元素唯一               插入有序      .size、has ~O(1)             哈希快            纯净无原型      for/of、forEach

典型选型

对象(Object):固定 schema、键均为字符串的配置、与 JSON 互转频繁的 DTO。 Map:键可能为 DOM 节点/对象、cache.set(obj, derived)、需按插入顺序稳定遍历。 数组(Array):需要排序、splice、按索引读写、或与后端列表一一对应的序列语义。 Set:用户 ID、标签枚举、爬虫 URL 判重、[...new Set(arr)] 一次性去重。

注意

  • Set 与 Map 都按插入顺序迭代(规范要求)。
  • Set 没有「键」只有「值」;若需要键值对请用 Map。