一、Set 与 Map 的核心区别
| 维度 | Set | Map |
|---|---|---|
| 存储内容 | 存储单个值(value) 的集合 | 存储键值对(key-value) 的集合 |
| 唯一性依据 | 集合中的值(value) 唯一,重复值会被忽略 | 集合中的键(key) 唯一,相同键会覆盖旧值 |
| 核心用途 | 用于存储不重复的元素(如去重、检查元素是否存在) | 用于键值映射(如存储键对应的关联信息) |
| 键的特性 | 可看作 “键和值相同” 的特殊集合(forEach 回调中 key 与 value 一致) | 键可以是任意类型(原始值、对象等),且严格区分引用(如两个不同对象即使内容相同也视为不同键) |
| 迭代方式 | 迭代器返回单个值(如 for...of 循环直接取 value) | 迭代器返回 **[key, value] 数组 **(如 for...of 循环需解构) |
| 常用方法 | add(value)、has(value)、delete(value) | set(key, value)、has(key)、delete(key)、get(key) |
二、通常还会与哪些数据结构比较?
1. 与 对象(Object) 比较(主要针对 Map)
Map 和对象都是 “键值对” 存储结构,但核心差异如下:
- 键的类型:对象的键只能是 字符串或
Symbol(非字符串键会被自动转为字符串,如obj[{}]实际键是"[object Object]");Map的键可以是任意类型(原始值、对象、函数等),且保留引用唯一性。 - 原型链干扰:对象会继承原型链上的属性(如
obj.hasOwnProperty可能冲突);Map无原型链,仅包含自身存储的键值对。 - 长度获取:对象需通过
Object.keys(obj).length计算长度;Map直接通过size属性获取。 - 迭代便捷性:对象需先通过
Object.keys()/values()/entries()转换为数组才能迭代;Map本身是可迭代对象,支持for...of直接遍历。
2. 与 数组(Array) 比较(主要针对 Set)
Set 和数组都是 “值的集合”,但差异如下:
- 唯一性:
Set自动去重(重复值会被忽略);数组允许重复元素。 - 查找效率:
Set的has(value)方法时间复杂度为 O(1) (哈希表实现);数组的includes(value)/indexOf(value)时间复杂度为 O(n) (需遍历)。 - 访问方式:
Set无索引,不能通过下标访问元素;数组通过索引(arr[0])访问,支持有序操作(如slice、splice)。 - 适用场景:
Set适合去重、快速判断元素是否存在;数组适合需要有序访问、索引操作或重复元素的场景。
3. 与 WeakSet、WeakMap 比较
WeakSet 和 WeakMap 是 “弱引用” 版本的集合,与 Set/Map 的核心差异是内存管理:
- 引用类型:
WeakSet只能存储对象(不能存原始值),WeakMap的键必须是对象(值可以是任意类型);Set/Map可存储任意类型。 - 弱引用特性:
WeakSet/WeakMap对对象的引用是 “弱引用”—— 若对象没有其他强引用,会被垃圾回收机制回收,同时自动从集合中删除;Set/Map对对象是 “强引用”,会阻止垃圾回收。 - 功能限制:
WeakSet/WeakMap没有size属性,不支持迭代(for...of),也没有clear()方法;Set/Map支持这些功能。 - 适用场景:
WeakSet/WeakMap适合临时存储对象相关信息(如避免内存泄漏);Set/Map适合需要长期存储、迭代或统计数量的场景。
总结
Set是 “去重的值集合”,Map是 “键唯一的键值对集合”,核心差异在存储内容和用途。- 常与对象(键值对对比)、数组(值集合对比)、
WeakSet/WeakMap(内存管理对比)进行比较,选择时需根据是否需要去重、键类型、迭代需求、内存管理等场景判断。