JavaScript 中 Set 与 WeakSet 的区别、联系及示例
核心区别
| 特性 | Set | WeakSet |
|---|
| 值的类型 | 允许任意类型的值(对象、原始值) | 值必须是对象(非原始值) |
| 垃圾回收 | 强引用值 → 阻止垃圾回收 | 弱引用值 → 不影响垃圾回收 |
| 可遍历性 | 支持遍历(keys(), values(), for...of) | 不可遍历(无遍历方法) |
| Size 属性 | 有 size 属性获取元素数量 | 无 size 属性 |
| 清除方法 | 有 clear() 方法 | 无 clear() 方法 |
| 初始化 | 可初始化值(new Set([1, 2])) | 必须逐项添加(不能初始化) |
| 性能 | 适合存储长期存在的数据 | 内存优化(自动清理无引用值) |
核心联系
- 集合特性
二者均为值唯一的集合:add(value) / has(value) / delete(value) - 值唯一性
集合中每个值都是唯一的(基于严格相等 ===) - 相同方法
都支持 add(), has(), delete() 方法
代码示例
1. Set 基本用法
const users = new Set();
users.add("Alice");
users.add(42);
users.add({ id: 1 }); console.log(users.size);
console.log(users.has(42));
for (const user of users) {console.log(user);
}
2. WeakSet 基本用法
const userObjects = new WeakSet();
const alice = { name: "Alice" };
const bob = { name: "Bob" };
userObjects.add(alice);
userObjects.add(bob);
console.log(userObjects.has(alice));
alice = null;
高级场景示例
场景 1:Set 实现数组去重
const duplicates = [1, 2, 2, 3, 4, 4];
const unique = [...new Set(duplicates)];
const objSet = new Set([{id:1}, {id:1}]);
console.log(objSet.size);
场景 2:WeakSet 检测对象存在性
const activeSessions = new WeakSet();function startSession(user) {if (activeSessions.has(user)) {console.log("Session already exists!");return;}activeSessions.add(user);console.log("New session started");
}const user = { id: 1001 };
startSession(user);
startSession(user);
user = null;
场景 3:WeakSet 实现私有属性标记
const protectedFiles = new WeakSet();class FileSystem {constructor(file) {protectedFiles.add(file);this.file = file;}delete() {if (protectedFiles.has(this.file)) {throw Error("Protected file cannot be deleted");}}
}const secretFile = { name: "config.yml" };
const fs = new FileSystem(secretFile);fs.delete();
使用建议
| 场景 | 推荐 | 原因 |
|---|
| 数组去重 | Set | 高效值唯一性检查 |
| 需要遍历集合元素 | Set | 支持迭代器接口 |
| 存储原始值 | Set | WeakSet 不支持原始值 |
| 关联对象的临时状态 | WeakSet | 自动内存管理,避免泄漏 |
| 标记/验证对象存在性 | WeakSet | 轻量级且自动清理 |
| 长期存储数据集合 | Set | WeakSet 无法长期保留值 |
核心总结:
- 使用
Set 处理通用集合操作(遍历、去重、包含原始值) - 使用
WeakSet 处理对象关联的临时状态(自动垃圾回收是核心优势)