JS WeakMap 详细用法:从基础到实战

WeakMap 是 ES6 新增的弱引用键值对集合,核心特点:
  1. 键必须是对象(不能是原始值:字符串 / 数字 / 布尔等)
  2. 键是弱引用:键对象没有其他引用时,会被垃圾回收自动清理(不造成内存泄漏)
  3. 不可枚举(没有 keys()/values()/forEach(),也不能用 for...of
  4. 只有核心方法set()/get()/has()/delete()

一、基础用法(完整示例)

// 1. 创建 WeakMap
const wm = new WeakMap();

// 2. 定义对象作为键(原始值不能做键)
let user = { name: "张三" };
let info = { age: 20 };

// 3. set(key, value):添加键值对
wm.set(user, "用户信息");
wm.set(info, { id: 1001 });

// 4. get(key):获取值
console.log(wm.get(user)); // 输出:用户信息

// 5. has(key):判断是否存在
console.log(wm.has(info)); // 输出:true

// 6. delete(key):删除键值对
wm.delete(info);
console.log(wm.has(info)); // 输出:false
 

错误用法(键不能是原始值)

// 报错:Invalid value used as weak map key
wm.set("字符串键", 123); 
wm.set(123, "数值键");
 

二、核心特性:弱引用(最重要!)

WeakMap键是弱引用,如果键对象不再被其他变量引用,垃圾回收机制会自动回收该对象,并从 WeakMap 中移除,不会造成内存泄漏

对比:Map 会造成内存泄漏,WeakMap 不会

// 1. 使用 Map(强引用)
let obj = { id: 1 };
const map = new Map();
map.set(obj, "数据");

obj = null; // 手动释放引用
// Map 中依然保留 obj,不会被回收 → 内存泄漏


// 2. 使用 WeakMap(弱引用)
let obj2 = { id: 2 };
const weakMap = new WeakMap();
weakMap.set(obj2, "数据");

obj2 = null; // 手动释放引用
// 没有其他引用 → 垃圾回收自动清理 obj2 和 weakMap 中的键值对
 

三、最常用实战场景

场景 1:给 DOM 元素附加数据(无内存泄漏)

操作 DOM 时,用 WeakMap 存储关联数据,DOM 被删除后数据自动回收:
const btn = document.querySelector("#btn");
const domData = new WeakMap();

// 给 DOM 绑定数据
domData.set(btn, { clickCount: 0 });

// 使用数据
btn.addEventListener("click", () => {
  const data = domData.get(btn);
  data.clickCount++;
  console.log(data.clickCount);
});

// DOM 被删除时 → WeakMap 自动清理,无内存泄漏
// btn.remove();
 

场景 2:私有属性(模拟类的私有数据)

利用 WeakMap 实现真正私有(外部无法访问,不会被遍历):
const _private = new WeakMap();

class User {
  constructor(name) {
    // 私有数据存在 WeakMap 中
    _private.set(this, { name });
  }

  getName() {
    return _private.get(this).name;
  }
}

const u = new User("李四");
console.log(u.getName()); // 李四
console.log(u.name); // undefined(真正私有)
 

场景 3:缓存对象关联数据

const cache = new WeakMap();

// 缓存计算结果
function getCachedData(obj) {
  if (cache.has(obj)) {
    return cache.get(obj);
  }
  // 模拟耗时计算
  const result = obj.id * 100;
  cache.set(obj, result);
  return result;
}
 

四、WeakMap 可用方法汇总

方法 作用
wm.set(keyObj, value) 添加 / 更新键值对
wm.get(keyObj) 获取对应值
wm.has(keyObj) 判断是否存在,返回布尔值
wm.delete(keyObj) 删除指定键值对
wm.clear() 已废弃,不要使用

五、WeakMap vs Map(关键区别)

特性 WeakMap Map
键类型 只能是对象 任意类型(对象 / 字符串 / 数字等)
引用类型 弱引用(自动垃圾回收) 强引用(不会自动回收)
内存泄漏 不会 可能会
枚举 不可枚举(无迭代) 可枚举(keys/values/entries)
大小 size 属性 size

总结

  1. 什么时候用 WeakMap
    • 对象附加额外数据
    • DOM 元素关联数据
    • 类私有属性
    • 不想造成内存泄漏的缓存
  2. 记住核心键必须是对象 + 弱引用自动回收 + 不可枚举
  3. 它是专门为避免对象关联数据造成内存泄漏设计的 API
 
posted @ 2026-05-22 09:12  chenlight  阅读(2)  评论(0)    收藏  举报