JS中的 WeakSet 和 WeakMap

在JavaScript中,WeakSetWeakMap 是两个相对较少被提及但非常有用的集合类型。它们与我们熟悉的 MapSet 类似,但有一些独特的特性和用途。

一、从对象和 Map 开始

在深入探讨 WeakSetWeakMap 之前,我们先简单回顾一下 JavaScript 中的对象和 Map

对象

对象是 JavaScript 中最常用的数据结构之一。它是一个键值对的集合,键和值都可以是任意类型。例如:

javascript 复制代码
const algorithm = { site: "leetcode" };
console.log(algorithm.site); // leetcode

for (const key in algorithm) {
  console.log(key, algorithm[key]);
}

// site leetcode
delete algorithm.site;
console.log(algorithm.site); // undefined

对象的属性可以通过点符号(.)访问,也可以通过中括号([])访问。对象的属性可以通过 delete 关键字删除。

Map

Map 是一个更强大的集合类型,它允许键和值为任意类型。与对象不同,Map 的键是唯一的,且 Map 是可迭代的。例如:

javascript 复制代码
const map = new Map();
map.set('name', 'john');
map.set('phone', 'iPhone');
console.log(map.get('phone')); // iPhone
console.log(map.has('phone')); // true
console.log(map.size); // 2

for (const item of map) {
  console.dir(item);
}
// Array(2) ["name", "john"]
// Array(2) ["phone", "iPhone"]

Map 提供了许多有用的方法,如 setgethasdeleteclear

二、WeakMap

WeakMapMap 的一个变种,它与 Map 非常相似,但有一些关键的区别。

特性

  1. 键必须是对象WeakMap 的键必须是对象,不能是原始类型(如字符串、数字等)。例如:

    javascript 复制代码
    const John = { name: 'John' };
    const weakMap = new WeakMap();
    weakMap.set(John, 'student');
    // WeakMap {{...} => "student"}
    weakMap.set('john', 'student');
    // Uncaught TypeError: Invalid value used as weak map key
  2. 弱引用WeakMap 的键是弱引用的。这意味着如果一个对象只被 WeakMap 引用,而没有其他引用指向它,那么这个对象可能会被垃圾回收器回收。例如:

    javascript 复制代码
    let John = { major: "math" };
    const weakMap = new WeakMap();
    weakMap.set(John, 'student');
    John = null; // John 被垃圾回收
  3. 不可迭代WeakMap 不支持迭代方法,如 keysvaluesentries。因此,你无法直接遍历 WeakMap 中的键值对。

方法

WeakMap 提供了以下方法:

  • set(key, value):设置键值对。
  • get(key):获取键对应的值。
  • has(key):检查是否存在某个键。
  • delete(key):删除某个键。

使用场景

WeakMap 通常用于以下场景:

  1. 私有数据存储 :由于 WeakMap 的键是弱引用的,且不可迭代,它非常适合用于存储私有数据。例如,你可以为一个对象存储一些私有状态,而不用担心这些状态会泄漏到其他地方。

    javascript 复制代码
    const privateData = new WeakMap();
    const obj = { public: 'public' };
    privateData.set(obj, 'private');
    console.log(privateData.get(obj)); // private
  2. 缓存WeakMap 可以用于缓存对象的某些计算结果。由于键是弱引用的,当对象被垃圾回收时,对应的缓存也会自动清除。

    javascript 复制代码
    const cache = new WeakMap();
    const obj = { data: 'some data' };
    cache.set(obj, processData(obj.data));

三、WeakSet

WeakSetSet 的一个变种,它也具有一些独特的特性。

特性

  1. 成员必须是对象WeakSet 的成员必须是对象,不能是原始类型。例如:

    javascript 复制代码
    const John = { name: 'John' };
    const weakSet = new WeakSet();
    weakSet.add(John);
    // WeakSet {{...}}
    weakSet.add('john');
    // Uncaught TypeError: Invalid value used as weak set key
  2. 弱引用WeakSet 中的对象是弱引用的。如果一个对象只被 WeakSet 引用,而没有其他引用指向它,那么这个对象可能会被垃圾回收器回收。例如:

    javascript 复制代码
    let John = { major: "math" };
    const weakSet = new WeakSet();
    weakSet.add(John);
    John = null; // John 被垃圾回收
  3. 不可迭代WeakSet 不支持迭代方法,如 forEach。因此,你无法直接遍历 WeakSet 中的成员。

方法

WeakSet 提供了以下方法:

  • add(value):添加一个成员。
  • delete(value):删除一个成员。
  • has(value):检查是否包含某个成员。

使用场景

WeakSet 通常用于以下场景:

  1. 对象标记 :你可以使用 WeakSet 来标记某些对象,而不用担心这些对象会泄漏。例如,你可以标记某些对象为"已处理"或"已验证"。

    javascript 复制代码
    const processed = new WeakSet();
    const obj = { data: 'some data' };
    processed.add(obj);
    console.log(processed.has(obj)); // true
  2. 对象池WeakSet 可以用于管理对象池。当对象被垃圾回收时,它们会自动从 WeakSet 中移除,从而避免内存泄漏。

    javascript 复制代码
    const objectPool = new WeakSet();
    const obj = { data: 'some data' };
    objectPool.add(obj);

四、总结

WeakMapWeakSet 是 JavaScript 中非常有用的集合类型,它们提供了弱引用的特性,这使得它们在某些场景下非常有用。WeakMap 适用于存储私有数据和缓存,而 WeakSet 适用于对象标记和对象池管理。由于它们的弱引用特性,它们可以帮助我们避免内存泄漏,同时保持代码的简洁和高效。

相关推荐
鱼雀AIGC3 分钟前
如何仅用AI开发完整的小程序<6>—让AI对视觉效果进行升级
前端·人工智能·游戏·小程序·aigc·ai编程
duanyuehuan32 分钟前
Vue 组件定义方式的区别
前端·javascript·vue.js
veminhe36 分钟前
HTML5简介
前端·html·html5
洪洪呀36 分钟前
css上下滚动文字
前端·css
ん贤1 小时前
操作系统概述
面试·操作系统·王道
搏博1 小时前
基于Vue.js的图书管理系统前端界面设计
前端·javascript·vue.js·前端框架·数据可视化
掘金安东尼2 小时前
前端周刊第419期(2025年6月16日–6月22日)
前端·javascript·面试
bemyrunningdog2 小时前
AntDesignPro前后端权限按钮系统实现
前端
重阳微噪2 小时前
Data Config Admin - 优雅的管理配置文件
前端
Hilaku2 小时前
20MB 的字体文件太大了,我们把 Icon Font 压成了 10KB
前端·javascript·css