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 适用于对象标记和对象池管理。由于它们的弱引用特性,它们可以帮助我们避免内存泄漏,同时保持代码的简洁和高效。

相关推荐
禁止摆烂_才浅8 分钟前
VsCode 概览尺、装订线、代码块高亮设置
前端·visual studio code
程序员猫哥35 分钟前
vue跳转页面的几种方法(推荐)
前端
代码老y1 小时前
十年回望:Vue 与 React 的设计哲学、演进轨迹与生态博弈
前端·vue.js·react.js
一条上岸小咸鱼1 小时前
Kotlin 基本数据类型(五):Array
android·前端·kotlin
zzywxc7871 小时前
详细探讨AI在金融、医疗、教育和制造业四大领域的具体落地案例,并通过代码、流程图、Prompt示例和图表等方式展示这些应用的实际效果。
开发语言·javascript·人工智能·深度学习·金融·prompt·流程图
大明881 小时前
用 mouseover/mouseout 事件代理模拟 mouseenter/mouseleave
前端·javascript
小杨梅君1 小时前
vue3+vite中使用自定义element-plus主题配置
前端·element
一个专注api接口开发的小白1 小时前
Python + 淘宝 API 开发:自动化采集商品数据的完整流程
前端·数据挖掘·api
林太白1 小时前
Nuxt.js搭建一个官网如何简单
前端·javascript·后端
晴空雨1 小时前
一个符号让 indexOf 判断更优雅!JavaScript 位运算的隐藏技巧
前端·javascript