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

典型场景

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 版本)
相关推荐
小小小小宇2 小时前
前端 Service Worker
前端
只喜欢赚钱的棉花没有糖2 小时前
http的缓存问题
前端·javascript·http
小小小小宇2 小时前
请求竞态问题统一封装
前端
loriloy2 小时前
前端资源帖
前端
源码超级联盟2 小时前
display的block和inline-block有什么区别
前端
GISer_Jing3 小时前
前端构建工具(Webpack\Vite\esbuild\Rspack)拆包能力深度解析
前端·webpack·node.js
让梦想疯狂3 小时前
开源、免费、美观的 Vue 后台管理系统模板
前端·javascript·vue.js
海云前端3 小时前
前端写简历有个很大的误区,就是夸张自己做过的东西。
前端
葡萄糖o_o3 小时前
ResizeObserver的错误
前端·javascript·html
AntBlack3 小时前
Python : AI 太牛了 ,撸了两个 Markdown 阅读器 ,谈谈使用感受
前端·人工智能·后端