TypeScript Set/WeakMap
Set 是 ES6 引入的「集合」:存放一组不重复的值,常用于去重与存在性判断;WeakSet 与 WeakMap 是弱引用版本,专门以对象为键、不阻止垃圾回收,适合做缓存与临时标记。
创建 Set 与基本操作
add 添加、delete 删除、has 判断、size 取长度,重复值会被自动忽略:
let s: Set<number> = new Set();
s.add(1);
s.add(2);
s.add(1); // 重复,被忽略
console.log(s.size); // 输出:2
console.log(s.has(1)); // 输出:true
s.delete(2);
console.log(s.size); // 输出:1
用 Set 去重
把数组传入 Set 再展开,即可快速去重,得到的结果仍是数组:
let nums: number[] = [1, 2, 2, 3, 3, 3];
let unique: number[] = [...new Set(nums)];
console.log(unique); // 输出:[ 1, 2, 3 ]
遍历 Set
for...of 与 forEach 都可以遍历,元素按插入顺序输出:
let tags: Set<string> = new Set(["ts", "js", "ts"]);
for (let t of tags) {
console.log(t); // 输出:ts / js
}
tags.forEach((t) => console.log("标签:" + t)); // 输出:标签:ts / 标签:js
WeakSet:只能存对象
WeakSet 的元素只能是对象,不支持遍历、没有 size,只有 add / has / delete。它持有弱引用:对象失去其他引用被回收后,会自动从 WeakSet 中消失:
let visited = new WeakSet<object>();
let user = { id: 1 };
visited.add(user);
console.log(visited.has(user)); // 输出:true
// visited.add("str"); // 报错:WeakSet 只能添加对象
user = null; // 原对象失去引用,可被垃圾回收
WeakMap:弱引用的键值对
WeakMap 的键必须是对象、不可遍历。它常用于给对象附带额外信息而不影响其生命周期,例如缓存计算结果:
let cache = new WeakMap<object, number>();
function fib(n: number): number {
return n <= 1 ? n : fib(n - 1) + fib(n - 2);
}
let key = { input: 10 };
cache.set(key, fib(10));
console.log(cache.get(key)); // 输出:55
key = null; // 键失去引用后,缓存条目可被垃圾回收
泛型标注
Set / WeakSet / WeakMap 都是泛型类型,建议显式标注元素或键的类型:
let ids: Set<number> = new Set();
let users: WeakSet<{ id: number }> = new WeakSet();
let scores: WeakMap<object, number> = new WeakMap();
console.log(ids.size, users.has({ id: 1 }), scores.get({}));
// 输出:0 false undefined
小结
Set 专治「去重与存在性判断」,WeakSet/WeakMap 用弱引用实现不泄漏内存的缓存与标记。选择要点:需要遍历或求长度就用 Set/Map,只做对象关联则用 WeakSet/WeakMap。