JavaScript中的Map、WeakMap、Set、WeakSet详解
字数 1387 2025-11-14 23:09:55

JavaScript中的Map、WeakMap、Set、WeakSet详解

1. 描述
Map、WeakMap、Set、WeakSet是ES6引入的四种集合类型,用于存储数据集合。它们与普通对象和数组不同,具有特定的用途和内存管理特性。理解它们的区别和适用场景是JavaScript开发中的重要知识点。


2. Map(映射)
定义:Map是一种键值对集合,键可以是任意类型(对象、函数、基本类型等),而普通对象的键只能是字符串或Symbol。
特点

  • 保持键的插入顺序。
  • 可通过size属性直接获取元素数量。
  • 无需担心键名与原型属性冲突(如toString等)。

常用方法

const map = new Map();
map.set('key', 'value');     // 添加键值对
map.get('key');              // 获取值 → "value"
map.has('key');              // 检查键是否存在 → true
map.delete('key');           // 删除键值对
map.clear();                 // 清空集合
map.size;                    // 返回元素数量

与Object的区别

  • Map的键可以是任意类型,Object的键只能是字符串或Symbol。
  • Map直接支持迭代(for...offorEach),Object需要先获取键数组。
  • Map在频繁增删键值对的场景下性能更好。

3. WeakMap(弱映射)
定义:键必须是对象(非基本类型),值可以是任意类型。
核心特性:弱引用——如果键对象没有被其他引用,则会被垃圾回收(即使WeakMap中仍存在该键)。
限制

  • 不可迭代(没有keys()values()forEach等方法)。
  • 没有size属性(因垃圾回收可能导致大小动态变化)。

适用场景

  • 存储与对象关联的私有数据(避免内存泄漏):
const privateData = new WeakMap();
class Person {
  constructor(name) {
    privateData.set(this, { name }); // 以实例为键存储数据
  }
  getName() {
    return privateData.get(this).name;
  }
}
// 当实例被销毁时,关联数据自动被回收

4. Set(集合)
定义:存储唯一值的集合,值可以是任意类型。
特点

  • 值不会重复(基于SameValueZero算法,类似===,但认为NaN === NaN)。
  • 保持插入顺序。

常用方法

const set = new Set();
set.add(1);                  // 添加值
set.add(2);
set.has(1);                  // 检查值是否存在 → true
set.delete(1);               // 删除值
set.size;                    // 元素数量 → 1

应用场景

  • 数组去重:[...new Set([1, 2, 2, 3])] // [1, 2, 3]
  • 记录已处理过的对象(避免重复操作)。

5. WeakSet(弱集合)
定义:值必须是对象,且弱引用(对象无其他引用时会被回收)。
限制

  • 不可迭代,无size属性。
  • 仅支持add()has()delete()方法。

适用场景

  • 标记对象(如检查对象是否已处理过):
const markedItems = new WeakSet();
const obj = {};
markedItems.add(obj);
if (markedItems.has(obj)) {
  // 对象已被标记
}
// 当obj被销毁时,自动从WeakSet中移除

6. 关键区别总结

类型 键/值要求 是否可迭代 垃圾回收特性
Map 任意类型键 强引用(可能内存泄漏)
WeakMap 键必须是对象 弱引用(自动回收)
Set 任意类型值 强引用
WeakSet 值必须是对象 弱引用

7. 内存管理示例

// 强引用示例(Map可能导致内存泄漏)
let obj = { id: 1 };
const map = new Map();
map.set(obj, "data");
obj = null; // obj仍被Map引用,不会被垃圾回收

// 弱引用示例(WeakMap自动回收)
let obj2 = { id: 2 };
const weakMap = new WeakMap();
weakMap.set(obj2, "data");
obj2 = null; // obj2无其他引用,将被垃圾回收

8. 实践建议

  • 需要存储键值对且键类型多样时,用Map
  • 需要关联对象与数据且避免内存泄漏时,用WeakMap
  • 需要存储唯一值列表时,用Set
  • 需要标记对象状态且避免干扰回收时,用WeakSet
JavaScript中的Map、WeakMap、Set、WeakSet详解 1. 描述 Map、WeakMap、Set、WeakSet是ES6引入的四种集合类型,用于存储数据集合。它们与普通对象和数组不同,具有特定的用途和内存管理特性。理解它们的区别和适用场景是JavaScript开发中的重要知识点。 2. Map(映射) 定义 :Map是一种键值对集合,键可以是任意类型(对象、函数、基本类型等),而普通对象的键只能是字符串或Symbol。 特点 : 保持键的插入顺序。 可通过 size 属性直接获取元素数量。 无需担心键名与原型属性冲突(如 toString 等)。 常用方法 : 与Object的区别 : Map的键可以是任意类型,Object的键只能是字符串或Symbol。 Map直接支持迭代( for...of 、 forEach ),Object需要先获取键数组。 Map在频繁增删键值对的场景下性能更好。 3. WeakMap(弱映射) 定义 :键必须是对象(非基本类型),值可以是任意类型。 核心特性 :弱引用——如果键对象没有被其他引用,则会被垃圾回收(即使WeakMap中仍存在该键)。 限制 : 不可迭代(没有 keys() 、 values() 、 forEach 等方法)。 没有 size 属性(因垃圾回收可能导致大小动态变化)。 适用场景 : 存储与对象关联的私有数据(避免内存泄漏): 4. Set(集合) 定义 :存储唯一值的集合,值可以是任意类型。 特点 : 值不会重复(基于 SameValueZero 算法,类似 === ,但认为 NaN === NaN )。 保持插入顺序。 常用方法 : 应用场景 : 数组去重: [...new Set([1, 2, 2, 3])] // [1, 2, 3] 记录已处理过的对象(避免重复操作)。 5. WeakSet(弱集合) 定义 :值必须是对象,且弱引用(对象无其他引用时会被回收)。 限制 : 不可迭代,无 size 属性。 仅支持 add() 、 has() 、 delete() 方法。 适用场景 : 标记对象(如检查对象是否已处理过): 6. 关键区别总结 | 类型 | 键/值要求 | 是否可迭代 | 垃圾回收特性 | |-----------|----------------|------------|------------------| | Map | 任意类型键 | 是 | 强引用(可能内存泄漏) | | WeakMap | 键必须是对象 | 否 | 弱引用(自动回收) | | Set | 任意类型值 | 是 | 强引用 | | WeakSet | 值必须是对象 | 否 | 弱引用 | 7. 内存管理示例 8. 实践建议 需要存储键值对且键类型多样时,用 Map 。 需要关联对象与数据且避免内存泄漏时,用 WeakMap 。 需要存储唯一值列表时,用 Set 。 需要标记对象状态且避免干扰回收时,用 WeakSet 。