大家好,我是第八哥,作为一名有10年前端开发经验的工程师,我发现很多初学者甚至部分老手,在用JavaScript的Map和Set时,往往只停留在会用的层面,而不了解它们的底层原理与高效用法。今天我会带你从零开始,全面掌握Map和Set的使用技巧,并结合实战案例深入解析。
一、为什么需要Map和Set?
在ES6之前,我们主要用Object
和Array
来存储键值对和去重。但随着应用复杂度的提升,这两种结构存在以下局限:
- • Object的key只能是字符串或Symbol,不够灵活。
- • Array去重性能低,需要额外逻辑。
- • 数据查找和删除效率低,尤其是大数据量。
ES6新增的Map
和Set
正是为了解决这些问题,让数据结构更高效、可读性更强。
二、Map的核心用法
Map是专门存储键值对的结构,支持任何类型的key,比Object
更强大。
1. 创建和基本操作
const map = new Map();
map.set('name', 'Jack');
map.set(1, '数字键');
map.set({ id: 1 }, '对象键');
console.log(map.get('name')); // Jack
console.log(map.has(1)); // true
map.delete('name');
console.log(map.size); // 2
2. 遍历技巧
Map天然支持迭代,主要有以下三种方式:
for (const [key, value] of map) {
console.log(key, value);
}
map.forEach((value, key) => console.log(key, value));
console.log([...map.keys()]);
console.log([...map.values()]);
3. 与Object的对比
特性 | Object | Map |
---|---|---|
键类型 | 字符串/符号 | 任意类型 |
遍历顺序 | 无需 | 插入顺序 |
性能 | 查找较慢 | 查找快 |
适用场景 | 简单结构 | 高性能键值对 |
三、Set的核心用法
Set用于存储唯一值,不会自动去重。
1. 基本操作
const set = new Set([1, 2, 3, 3]);
console.log(set); // Set {1,2,3}
set.add(4);
console.log(set.has(2)); // true
set.delete(1);
console.log(set.size); // 3
2. 数组去重与交集并集
const arr = [1, 2, 2, 3, 4, 4];
const unique = [...new Set(arr)]; // [1,2,3,4]
const a = new Set([1, 2, 3]);
const b = new Set([3, 4, 5]);
const union = new Set([...a, ...b]); // 并集 {1,2,3,4,5}
const intersect = new Set([...a].filter(x => b.has(x))); // 交集 {3}
const diff = new Set([...a].filter(x => !b.has(x))); // 差集 {1,2}
3. WeakSet和WeakMap
如果你只需要存储对象引用,且希望在对象被垃圾回收后自动清理内存,可以用WeakSet
和WeakMap
,非常适合缓存场景。
四、实战案例:LRU缓存
我们可以用Map
快速实现一个LRU缓存,最近使用的放在最后,最久未用的被删除:
class LRUCache {
constructor(limit = 3) {
this.cache = new Map();
this.limit = limit;
}
get(key) {
if (!this.cache.has(key)) return -1;
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
put(key, value) {
if (this.cache.has(key)) this.cache.delete(key);
this.cache.set(key, value);
if (this.cache.size > this.limit) {
this.cache.delete(this.cache.keys().next().value);
}
}
}
const lru = new LRUCache(2);
lru.put('a', 1);
lru.put('b', 2);
lru.get('a');
lru.put('c', 3);
console.log([...lru.cache.keys()]); // ['a', 'c']
五、最佳实践
- • 大数据集合优先用
Map
和Set
,性能比Object
和Array
高。 - • 需要唯一性就用
Set
,需要键值映射就用Map
。 - • 使用
WeakMap
和WeakSet
优化内存管理。 - • 在循环中避免频繁
set.delete()
,可以先重新构建数据。
六、总结
Map和Set是ES6引入的高性能数据结构,能极大提升代码可读性和执行效率。掌握它们的高阶用法,比如LRU缓存、去重、集合运算,会让你的JavaScript更具表现力。
评论