author: 专注前端开发,分享JavaScript干货
title: JavaScript进阶③|Map_Set_WeakMap_WeakSet,新型数据结构
update: 2026-04-28
tags: JavaScript,Map,Set,WeakMap,WeakSet,数据结构,ES6,前端进阶
作者:专注前端开发,分享JavaScript干货
更新时间:2026年4月
适合人群:掌握ES6基础,想了解新型数据结构的开发者
前言:为什么需要 Map 和 Set?
传统对象 {} 只能用字符串或 Symbol 作为键,数组也不能保证元素唯一。
ES6 的 Map 和 Set 解决了这些问题。
一、Set(集合)
1.1 基本用法
javascript
// 创建 Set(自动去重)
const set = new Set([1, 2, 2, 3, 3, 4]);
console.log(set); // Set(4) {1, 2, 3, 4}
// 添加元素
set.add(5);
console.log(set); // Set(5) {1, 2, 3, 4, 5}
// 删除元素
set.delete(3);
console.log(set); // Set(4) {1, 2, 4, 5}
// 检查是否存在
console.log(set.has(2)); // true
console.log(set.has(10)); // false
// 获取大小
console.log(set.size); // 4
// 清空
set.clear();
console.log(set.size); // 0
1.2 Set 的迭代
javascript
const set = new Set(["苹果", "香蕉", "橙子"]);
// for...of 遍历
for (const item of set) {
console.log(item);
}
// forEach 遍历
set.forEach((value, valueAgain, set) => {
console.log(value); // 注意:value 和 valueAgain 相同
});
// 转数组
const arr = [...set];
console.log(arr); // ["苹果", "香蕉", "橙子"]
1.3 Set 的常见用途
javascript
// 1. 数组去重
const arr = [1, 2, 2, 3, 3, 3, 4];
const unique = [...new Set(arr)];
console.log(unique); // [1, 2, 3, 4]
// 2. 求并集
const set1 = new Set([1, 2, 3]);
const set2 = new Set([2, 3, 4]);
const union = new Set([...set1, ...set2]);
console.log([...union]); // [1, 2, 3, 4]
// 3. 求交集
const intersection = new Set([...set1].filter(x => set2.has(x)));
console.log([...intersection]); // [2, 3]
// 4. 求差集
const difference = new Set([...set1].filter(x => !set2.has(x)));
console.log([...difference]); // [1]
二、Map(映射)
2.1 基本用法
javascript
// 创建 Map
const map = new Map();
// 设置键值对(键可以是任意类型)
map.set("name", "张三");
map.set(123, "数字键");
map.set(true, "布尔键");
map.set({}, "对象键");
// 获取值
console.log(map.get("name")); // "张三"
console.log(map.get(123)); // "数字键"
// 检查键是否存在
console.log(map.has("name")); // true
// 删除键值对
map.delete("name");
// 获取大小
console.log(map.size); // 3
// 清空
map.clear();
2.2 Map 与 Object 的区别
| 特性 | Map | Object |
|---|---|---|
| 键的类型 | 任意类型 | 字符串或 Symbol |
| 键的顺序 | 插入顺序 | ES2015+ 保留字符串键的插入顺序 |
| 大小 | size 属性 |
需要 Object.keys(obj).length |
| 迭代 | 可直接迭代 | 需要先获取键数组 |
| 性能 | 频繁增删键值对时更好 | 适合存储固定结构数据 |
2.3 Map 的迭代
javascript
const map = new Map([
["name", "张三"],
["age", 25],
["city", "北京"]
]);
// for...of 遍历(解构)
for (const [key, value] of map) {
console.log(`${key}: ${value}`);
}
// forEach 遍历
map.forEach((value, key) => {
console.log(`${key} = ${value}`);
});
// 只遍历键
for (const key of map.keys()) {
console.log(key);
}
// 只遍历值
for (const value of map.values()) {
console.log(value);
}
// 转对象(键需要是字符串)
const obj = Object.fromEntries(map);
console.log(obj); // { name: "张三", age: 25, city: "北京" }
2.4 Map 的初始化
javascript
// 方式1:传入二维数组
const map1 = new Map([
["name", "张三"],
["age", 25]
]);
// 方式2:从对象创建
const obj = { name: "张三", age: 25 };
const map2 = new Map(Object.entries(obj));
// 方式3:从另一个 Map 创建
const map3 = new Map(map1);
三、WeakMap 和 WeakSet
3.1 WeakSet
javascript
// WeakSet 只能存储对象,且是弱引用
const weakSet = new WeakSet();
let obj = { name: "张三" };
weakSet.add(obj);
console.log(weakSet.has(obj)); // true
// 当 obj 不再被引用时,会被垃圾回收(WeakSet 中的引用不会影响回收)
obj = null; // 现在 weakSet 中的对象可以被回收了
// 注意:WeakSet 不可迭代,也没有 size 属性
// weakSet.forEach(...); // ❌ 不存在
// console.log(weakSet.size); // ❌ 不存在
3.2 WeakMap
javascript
// WeakMap 的键只能是对象,值可以是任意类型
const weakMap = new WeakMap();
let key = { id: 1 };
weakMap.set(key, "值1");
console.log(weakMap.get(key)); // "值1"
// 当 key 不再被引用时,键值对会被垃圾回收
key = null; // 现在 weakMap 中的键值对可以被回收了
// 注意:WeakMap 不可迭代,也没有 size 属性
// weakMap.forEach(...); // ❌ 不存在
3.3 使用场景
javascript
// 场景1:私有数据(WeakMap)
const privateData = new WeakMap();
class User {
constructor(name) {
this.name = name;
privateData.set(this, { salary: 10000 });
}
getSalary() {
return privateData.get(this).salary;
}
}
const user = new User("张三");
console.log(user.getSalary()); // 10000
// privateData 中的用户数据不会阻止 user 被回收
// 场景2:缓存计算结果(WeakMap)
const cache = new WeakMap();
function process(obj) {
if (cache.has(obj)) {
return cache.get(obj);
}
const result = /* 复杂计算 */ obj.name + "已处理";
cache.set(obj, result);
return result;
}
四、知识卡
| 数据结构 | 特点 | 用途 |
|---|---|---|
Set |
元素唯一,任意类型 | 去重、集合运算 |
Map |
键值对,键任意类型 | 需要非字符串键的映射 |
WeakSet |
弱引用对象集合 | 标记对象、私有数据 |
WeakMap |
弱引用键值对 | 缓存、私有属性 |
五、课后作业
- 用 Set 实现数组去重,并统计每个元素出现的次数
- 用 Map 实现一个简单的 LRU 缓存(最近最少使用)
- 用 WeakMap 存储 DOM 元素的状态(如是否被点击过),不阻止垃圾回收
有问题欢迎评论区留言,大家一起讨论!
标签:JavaScript | Map | Set | WeakMap | WeakSet | 数据结构 | ES6 | 前端进阶