JavaScript中的Map、Set、WeakMap、WeakSet详解
字数 990 2025-11-12 23:14:07

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

今天我们来深入探讨JavaScript中的四种集合类型:Map、Set、WeakMap和WeakSet。这些数据结构在现代JavaScript开发中扮演着重要角色,提供了比传统对象和数组更专业的解决方案。

一、Map(映射)

描述:Map是一种键值对集合,与普通对象类似,但有着重要区别。

特点与使用场景

  1. 键可以是任意类型(对象、函数、基本类型等),而不仅仅是字符串或Symbol
  2. 保持插入顺序,遍历顺序与插入顺序一致
  3. 有专门的遍历方法和size属性

基本用法

// 创建Map
const map = new Map();

// 添加键值对
map.set('name', 'Alice');
map.set(1, 'number one');
map.set({}, 'object key');

// 获取值
console.log(map.get('name')); // 'Alice'

// 检查键是否存在
console.log(map.has(1)); // true

// 删除键值对
map.delete(1);

// 获取大小
console.log(map.size); // 2

遍历方法

const map = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3]
]);

// 遍历键
for (let key of map.keys()) {
  console.log(key); // 'a', 'b', 'c'
}

// 遍历值
for (let value of map.values()) {
  console.log(value); // 1, 2, 3
}

// 遍历键值对
for (let [key, value] of map.entries()) {
  console.log(key, value);
}

二、Set(集合)

描述:Set是一种值的集合,类似于数组,但值都是唯一的(没有重复项)。

特点与使用场景

  1. 存储唯一值,自动去重
  2. 保持插入顺序
  3. 判断值是否存在比数组更高效

基本用法

// 创建Set
const set = new Set();

// 添加值
set.add(1);
set.add(2);
set.add(2); // 重复值会被忽略
set.add('hello');

// 检查值是否存在
console.log(set.has(1)); // true

// 删除值
set.delete(2);

// 获取大小
console.log(set.size); // 2

// 数组去重示例
const numbers = [1, 2, 2, 3, 4, 4, 5];
const uniqueNumbers = [...new Set(numbers)];
console.log(uniqueNumbers); // [1, 2, 3, 4, 5]

遍历方法

const set = new Set([1, 2, 3]);

// 遍历值
for (let value of set) {
  console.log(value); // 1, 2, 3
}

// 使用forEach
set.forEach(value => {
  console.log(value);
});

三、WeakMap(弱映射)

描述:WeakMap是一种特殊的Map,键必须是对象,且键是弱引用。

关键特性

  1. 键必须是对象,不能是基本类型
  2. 键是弱引用,不会阻止垃圾回收
  3. 不可遍历,没有size属性
  4. 自动清理被垃圾回收的键对应的值

使用场景:私有数据存储、DOM元素元数据存储

// 创建WeakMap
const weakMap = new WeakMap();

// 键必须是对象
let obj1 = {};
let obj2 = { name: 'test' };

weakMap.set(obj1, 'private data 1');
weakMap.set(obj2, 'private data 2');

// 获取值
console.log(weakMap.get(obj1)); // 'private data 1'

// 当对象被垃圾回收时,对应的键值对会自动删除
obj1 = null; // 下次垃圾回收时,该键值对会被自动清理

四、WeakSet(弱集合)

描述:WeakSet是一种特殊的Set,值必须是对象,且值是弱引用。

关键特性

  1. 值必须是对象
  2. 值是弱引用,不会阻止垃圾回收
  3. 不可遍历,没有size属性

使用场景:对象标记、检查对象是否存在

// 创建WeakSet
const weakSet = new WeakSet();

let obj1 = { id: 1 };
let obj2 = { id: 2 };

weakSet.add(obj1);
weakSet.add(obj2);

// 检查对象是否存在
console.log(weakSet.has(obj1)); // true

// 删除对象
weakSet.delete(obj1);

// 对象被回收时自动移除
obj2 = null;

五、对比总结

特性 Map Set WeakMap WeakSet
键/值类型 任意类型 任意类型 对象 对象
可遍历
有size属性
弱引用
垃圾回收影响 自动清理 自动清理

六、实际应用示例

1. 使用Map缓存函数结果

function expensiveOperation(x) {
  console.log('Computing...');
  return x * x;
}

const cache = new Map();

function cachedOperation(x) {
  if (cache.has(x)) {
    return cache.get(x);
  }
  const result = expensiveOperation(x);
  cache.set(x, result);
  return result;
}

2. 使用WeakMap实现私有属性

const privateData = new WeakMap();

class Person {
  constructor(name, age) {
    privateData.set(this, { name, age });
  }
  
  getName() {
    return privateData.get(this).name;
  }
  
  getAge() {
    return privateData.get(this).age;
  }
}

3. 使用Set实现发布-订阅模式

class EventEmitter {
  constructor() {
    this.events = new Map();
  }
  
  on(event, callback) {
    if (!this.events.has(event)) {
      this.events.set(event, new Set());
    }
    this.events.get(event).add(callback);
  }
  
  emit(event, data) {
    if (this.events.has(event)) {
      this.events.get(event).forEach(callback => callback(data));
    }
  }
}

理解这些集合类型的特性和适用场景,能够帮助你在实际开发中选择最合适的数据结构,写出更高效、更健壮的代码。

JavaScript中的Map、Set、WeakMap、WeakSet详解 今天我们来深入探讨JavaScript中的四种集合类型:Map、Set、WeakMap和WeakSet。这些数据结构在现代JavaScript开发中扮演着重要角色,提供了比传统对象和数组更专业的解决方案。 一、Map(映射) 描述 :Map是一种键值对集合,与普通对象类似,但有着重要区别。 特点与使用场景 : 键可以是任意类型(对象、函数、基本类型等),而不仅仅是字符串或Symbol 保持插入顺序,遍历顺序与插入顺序一致 有专门的遍历方法和size属性 基本用法 : 遍历方法 : 二、Set(集合) 描述 :Set是一种值的集合,类似于数组,但值都是唯一的(没有重复项)。 特点与使用场景 : 存储唯一值,自动去重 保持插入顺序 判断值是否存在比数组更高效 基本用法 : 遍历方法 : 三、WeakMap(弱映射) 描述 :WeakMap是一种特殊的Map,键必须是对象,且键是弱引用。 关键特性 : 键必须是对象,不能是基本类型 键是弱引用,不会阻止垃圾回收 不可遍历,没有size属性 自动清理被垃圾回收的键对应的值 使用场景 :私有数据存储、DOM元素元数据存储 四、WeakSet(弱集合) 描述 :WeakSet是一种特殊的Set,值必须是对象,且值是弱引用。 关键特性 : 值必须是对象 值是弱引用,不会阻止垃圾回收 不可遍历,没有size属性 使用场景 :对象标记、检查对象是否存在 五、对比总结 | 特性 | Map | Set | WeakMap | WeakSet | |------|-----|-----|---------|---------| | 键/值类型 | 任意类型 | 任意类型 | 对象 | 对象 | | 可遍历 | 是 | 是 | 否 | 否 | | 有size属性 | 是 | 是 | 否 | 否 | | 弱引用 | 否 | 否 | 是 | 是 | | 垃圾回收影响 | 无 | 无 | 自动清理 | 自动清理 | 六、实际应用示例 1. 使用Map缓存函数结果 : 2. 使用WeakMap实现私有属性 : 3. 使用Set实现发布-订阅模式 : 理解这些集合类型的特性和适用场景,能够帮助你在实际开发中选择最合适的数据结构,写出更高效、更健壮的代码。