Set和WeakSet
# 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); // 3
console.log(users.has(42)); // true
// 遍历Set
for (const user of users) {
console.log(user); // "Alice", 42, {id:1}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 2. WeakSet 基本用法
const userObjects = new WeakSet();
const alice = { name: "Alice" };
const bob = { name: "Bob" };
// 只能添加对象引用
userObjects.add(alice); // ✅
userObjects.add(bob); // ✅
// userObjects.add("Charlie"); // ❌ TypeError
console.log(userObjects.has(alice)); // true
// 对象销毁后自动清理
alice = null; // 移除引用
// 垃圾回收后,WeakSet自动移除alice
// userObjects.has(alice) → false (无法直接验证)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 高级场景示例
# 场景 1:Set 实现数组去重
const duplicates = [1, 2, 2, 3, 4, 4];
const unique = [...new Set(duplicates)]; // [1, 2, 3, 4]
// 对象去重(需注意引用不同)
const objSet = new Set([{id:1}, {id:1}]);
console.log(objSet.size); // 2 (不同对象引用)
1
2
3
4
5
6
2
3
4
5
6
# 场景 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); // New session started
startSession(user); // Session already exists!
// 当用户退出时自动清理
user = null;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 场景 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(); // ❌ Error: Protected file cannot be deleted
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 使用建议
场景 | 推荐 | 原因 |
---|---|---|
数组去重 | Set | 高效值唯一性检查 |
需要遍历集合元素 | Set | 支持迭代器接口 |
存储原始值 | Set | WeakSet 不支持原始值 |
关联对象的临时状态 | WeakSet | 自动内存管理,避免泄漏 |
标记/验证对象存在性 | WeakSet | 轻量级且自动清理 |
长期存储数据集合 | Set | WeakSet 无法长期保留值 |
核心总结:
- 使用
Set
处理通用集合操作(遍历、去重、包含原始值)- 使用
WeakSet
处理对象关联的临时状态(自动垃圾回收是核心优势)
编辑 (opens new window)
上次更新: 2025/08/04, 08:16:58