Set 与 Map 深度解析:区别、特性与应用场景,弱引用版本对比:WeakSet 与 WeakMap

Set 与 Map 深度解析:区别、特性与应用场景

一、核心定义

数据类型 存储内容 键/值要求 重复性规则
Set 唯一值的集合 只有值(无键) 值不能重复
Map 键值对的集合 键值任意类型(包括对象引用) 键不能重复

简单对比:

  • Set:类似数组,但值唯一 [1, 2, 3]
  • Map:类似对象,但键可以是对象 { [obj]: "data" }

二、关键特性对比

特性 Set Map
初始化方式 new Set([1, 2, 3]) new Map([[k1,v1], [k2,v2]])
元素唯一性判断 值严格相等(===,但 NaN=NaN) 键严格相等(===,但 NaN=NaN)
元素访问 无索引,只能遍历或查存在 通过键访问:map.get(key)
顺序性 插入顺序保留 插入顺序保留
常用方法 add(), delete(), has() set(), get(), has()
大小获取 set.size map.size

三、核心方法详解

Set 操作示例:

arduino 复制代码
JavaScript
const set = new Set();
set.add("apple");          // 添加值
set.add("banana");
console.log(set.size);     // 2
console.log(set.has("apple")); // true
set.delete("banana");      // 删除
set.clear();               // 清空

Map 操作示例:

c 复制代码
JavaScript
const map = new Map();
const keyObj = { id: 1 };

map.set(keyObj, "data");     // 键为对象
map.set(123, "数字键");      // 键为数字
console.log(map.get(keyObj)); // "data"
map.delete(123);             // 删除键

四、特殊行为

  1. 重复值处理:

    • Set 添加重复值自动忽略:

      csharp 复制代码
      JavaScript
      const set = new Set();
      set.add(1).add(1); // 最终只有 1 个元素
    • Map 重复键会覆盖旧值:

      c 复制代码
      JavaScript
      map.set("key", "v1");
      map.set("key", "v2"); // 值变为 v2
  2. NaN 的特殊相等:

    arduino 复制代码
    JavaScript
    const set = new Set();
    set.add(NaN).add(NaN); // 只保留 1 个 NaN
    
    const map = new Map();
    map.set(NaN, "test");
    console.log(map.get(NaN)); // "test"(NaN 可作为键)

五、与弱引用版本对比:WeakSet 与 WeakMap

特性 WeakSet WeakMap 与普通版本区别
键要求 只接受对象作为值 只接受对象作为键 ✅ 键/值必须是对象引用
可遍历性 ❌ 不可遍历 ❌ 不可遍历 ✅ 无 size、keys() 等方法
垃圾回收 元素无引用时自动回收 键对象无引用时自动回收 ✅ 防止内存泄漏
应用场景 临时对象跟踪 对象关联元数据

典型场景:

kotlin 复制代码
JavaScript
// WeakMap 存储私有数据
const privateData = new WeakMap();

class Person {
  constructor(name) {
    privateData.set(this, { name }); // this 作键
  }
  getName() {
    return privateData.get(this).name;
  }
}

六、应用场景指南

场景描述 推荐数据结构 原因
存储唯一值(如用户ID) Set 自动去重,高效判断存在性
需要保留插入顺序的键值对 Map 比普通对象更可靠的顺序保证
键需为非字符串(如对象/函数) Map 普通对象键会自动转字符串
临时缓存对象(防内存泄漏) WeakSet/WeakMap 自动回收无引用的对象
为对象关联私有数据 WeakMap 键为对象本身,对象销毁时数据自动清除
交集/并集运算(如好友关系) Set 通过 union(), intersection() 等方法实现高效集合运算

七、性能关键点

  1. 查找效率:

    • Set.has(value) 和 Map.has(key) 的时间复杂度为 O(1) (哈希表实现),远快于数组的 includes()(O(n))
  2. 与数组转换:

    sql 复制代码
    JavaScript
    // Set → Array
    const arr = [...set]; 
    // Array → Set (去重)
    const set = new Set(arr);
  3. 遍历优化:

    arduino 复制代码
    JavaScript
    // Set 遍历
    for (const value of set) { ... }
    // Map 遍历
    for (const [key, value] of map) { ... }

总结

  • Set:处理唯一值集合,替代数组去重,高效值存在性检查
  • Map:键值对存储的升级版,支持任意类型键,保留插入顺序
  • WeakSet/WeakMap:专为对象设计的弱引用容器,防止内存泄漏
  • 性能优先 :高频查找用 Set/Map,数组遍历改用 for...of 或传统 for

优先选择 Set/Map 的场景:

  1. 需要维护插入顺序
  2. 键为非字符串
  3. 高频存在性检查
  4. 避免内存泄漏(用 Weak 版本)
相关推荐
kyriewen5 分钟前
别再用防抖做懒加载了:120 张图只加载出 4 张
前端·javascript·程序员
计算机魔术师11 分钟前
Hugging Face CEO 转评前 DOGE 研究人员用 AI 智能体渗透 Anthropic 系统事件
前端
IT_陈寒19 分钟前
刚解决一个 Java 并发问题,这坑踩得我怀疑人生
前端·人工智能·后端
前端一课19 分钟前
一个晚上,四个“小问题”:我重写了 12 章 ArkUI 笔记
前端
小码哥_常32 分钟前
前端图片压缩实战——我把网站图片体积砍了 70%
前端
张一凡931 小时前
把“不要乱改”从提示词里拿出来,放进可校验的提案里
前端·后端·架构
木子欢儿1 小时前
Debian 13 + vsftpd 搭建FTP服务
linux·服务器·前端·网络·debian
leeguoo1 小时前
让 Claude Code / Codex 用上你已登录的 Chrome
前端·chrome·ai编程
天蒙蒙亮1 小时前
打安卓apk包+“应用商城”发布
前端·uni-app
Lank_M1 小时前
视频压到指定大小总超一截?码率控制的误差拆开看
前端