JavaScript中的WeakMap和WeakSet有什么用?

来源:IPIPP.com作者:头衔:全栈工程师
导读:本期聚焦于小伙伴创作的《JavaScript中的WeakMap和WeakSet有什么用?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《JavaScript中的WeakMap和WeakSet有什么用?》有用,将其分享出去将是对创作者最好的鼓励。

JavaScript中的WeakMap和WeakSet是ES6引入的两种特殊数据结构,它们的核心特性和普通Map、Set不同,主要围绕弱引用设计,在内存管理和特定场景的数据关联上有独特作用。

JavaScript中的WeakMap和WeakSet有什么用?

WeakMap的基本特性与用法

WeakMap是一种键值对集合,它的键必须是对象,值可以是任意类型,且键对对象是弱引用关系,不会阻止垃圾回收。当WeakMap的键对象没有其他引用时,该键值对会被自动回收。

基本用法示例如下:

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

// 定义作为键的对象
const obj1 = { id: 1 };
const obj2 = { id: 2 };

// 设置键值对
weakMap.set(obj1, '关联数据1');
weakMap.set(obj2, '关联数据2');

// 获取值
console.log(weakMap.get(obj1)); // 输出:关联数据1

// 删除键值对
weakMap.delete(obj1);
console.log(weakMap.get(obj1)); // 输出:undefined

// 判断是否存在键
console.log(weakMap.has(obj2)); // 输出:true

WeakMap不支持遍历,也没有size属性,这是因为它的键值对可能随时被垃圾回收,无法保证遍历的准确性。

WeakSet的基本特性与用法

WeakSet是值的集合,它的成员必须是对象,且对成员对象是弱引用,同样不会阻止垃圾回收。当WeakSet的成员对象没有其他引用时,会被自动从集合中移除。

基本用法示例如下:

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

// 定义作为成员的对象
const item1 = { name: 'item1' };
const item2 = { name: 'item2' };

// 添加成员
weakSet.add(item1);
weakSet.add(item2);

// 判断是否存在成员
console.log(weakSet.has(item1)); // 输出:true

// 删除成员
weakSet.delete(item1);
console.log(weakSet.has(item1)); // 输出:false

和WeakMap一样,WeakSet也不支持遍历,没有size属性,无法获取集合中的所有成员。

WeakMap和WeakSet的核心作用

1. 避免内存泄漏

普通Map和Set对键或成员是强引用,即使外部不再使用该对象,只要Map或Set还持有引用,对象就不会被垃圾回收,可能造成内存泄漏。而WeakMap和WeakSet的弱引用特性可以避免这个问题。

比如给DOM元素关联私有数据,使用普通Map时,即使DOM元素被移除,Map仍然持有引用,元素无法被回收:

const domMap = new Map();
const dom = document.getElementById('test');
domMap.set(dom, { clickCount: 0 });

// 后续移除dom元素
dom.remove();
// 此时domMap仍然持有dom的引用,dom无法被垃圾回收

换成WeakMap后,当dom元素没有其他引用时,会被自动回收,对应的键值对也会消失:

const domWeakMap = new WeakMap();
const dom = document.getElementById('test');
domWeakMap.set(dom, { clickCount: 0 });

// 移除dom元素后,若没有其他引用,dom会被回收,WeakMap中的对应项也会自动清除
dom.remove();

2. 存储对象的私有数据

WeakMap可以用来存储对象的私有属性,因为WeakMap的键是对象,外部无法直接遍历获取所有关联的私有数据,相对更安全。

示例如下:

const privateData = new WeakMap();

class User {
  constructor(name) {
    this.name = name;
    // 存储私有数据,外部无法直接访问
    privateData.set(this, { age: 0, salary: 0 });
  }

  setAge(age) {
    const data = privateData.get(this);
    data.age = age;
  }

  getAge() {
    return privateData.get(this).age;
  }
}

const user = new User('张三');
user.setAge(20);
console.log(user.getAge()); // 输出:20
// 外部无法直接获取privateData中存储的内容

3. 标记对象状态

WeakSet可以用来标记对象是否处于某种状态,比如是否已经处理过、是否已经注册等,因为弱引用的特性,不会影响对象的生命周期。

示例如下:

const processedObjects = new WeakSet();

function processObject(obj) {
  // 如果已经处理过,直接返回
  if (processedObjects.has(obj)) {
    return;
  }
  // 处理对象逻辑
  console.log('处理对象', obj);
  // 标记为已处理
  processedObjects.add(obj);
}

const targetObj = { data: 'test' };
processObject(targetObj); // 输出:处理对象 { data: 'test' }
processObject(targetObj); // 无输出,因为已经处理过

使用注意事项

  • WeakMap的键、WeakSet的成员都必须是对象,不能是原始类型(如字符串、数字等)。
  • 两者都不支持遍历、size属性、clear方法,无法批量操作所有键值对或成员。
  • 只有在需要弱引用、避免内存泄漏的场景下才使用,普通数据关联场景用Map和Set更合适。

WeakMapWeakSetJavaScript弱引用内存管理修改时间:2026-06-03 00:30:10

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。