从零开始掌握JavaScript的Map和Set | 高效数据结构与实战技巧

大家好,我是第八哥,作为一名有10年前端开发经验的工程师,我发现很多初学者甚至部分老手,在用JavaScript的Map和Set时,往往只停留在会用的层面,而不了解它们的底层原理与高效用法。今天我会带你从零开始,全面掌握Map和Set的使用技巧,并结合实战案例深入解析。

一、为什么需要Map和Set?

在ES6之前,我们主要用ObjectArray来存储键值对和去重。但随着应用复杂度的提升,这两种结构存在以下局限:

  • Object的key只能是字符串或Symbol,不够灵活。
  • Array去重性能低,需要额外逻辑。
  • • 数据查找和删除效率低,尤其是大数据量。

ES6新增的MapSet正是为了解决这些问题,让数据结构更高效、可读性更强。

二、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的对比

特性ObjectMap
键类型字符串/符号任意类型
遍历顺序无需插入顺序
性能查找较慢查找快
适用场景简单结构高性能键值对

三、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

如果你只需要存储对象引用,且希望在对象被垃圾回收后自动清理内存,可以用WeakSetWeakMap,非常适合缓存场景。

四、实战案例: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']

五、最佳实践

  • • 大数据集合优先用MapSet,性能比ObjectArray高。
  • • 需要唯一性就用Set,需要键值映射就用Map
  • • 使用WeakMapWeakSet优化内存管理。
  • • 在循环中避免频繁set.delete(),可以先重新构建数据。

六、总结

Map和Set是ES6引入的高性能数据结构,能极大提升代码可读性和执行效率。掌握它们的高阶用法,比如LRU缓存、去重、集合运算,会让你的JavaScript更具表现力。

上一篇 使用Web Worker提升前端性能的实战技巧 | 多线程加速优化指南 下一篇 JavaScript事件循环工作原理详解 | 微任务与宏任务执行顺序解析

评论

暂不支持评论