[Medium] Set & Map
1. What are Set and Map?
什么是 Set 和 Map?
Set 和 Map 是 ES6 引入的两种新的数据结构,它们提供了比传统对象和数组更适合特定场景的解决方案。
Set(集合)
定义:Set 是一种值唯一的集合,类似于数学中的集合概念。
特点:
- 储存的值不会重复
- 使用
===来判断值是否相等 - 保持插入顺序
- 可以储存任何类型的值(原始类型或对象)
基本用法:
// 创建 Set
const set = new Set();
// 添加值
set.add(1);
set.add(2);
set.add(2); // 重复值不会被加入
set.add('hello');
set.add({ name: 'John' });
console.log(set.size); // 4
console.log(set); // Set(4) { 1, 2, 'hello', { name: 'John' } }
// 检查值是否存在
console.log(set.has(1)); // true
console.log(set.has(3)); // false
// 删除值
set.delete(2);
console.log(set.has(2)); // false
// 清空 Set
set.clear();
console.log(set.size); // 0
从数组创建 Set:
// 去除数组中的重复值
const arr = [1, 2, 2, 3, 3, 3];
const uniqueSet = new Set(arr);
console.log(uniqueSet); // Set(3) { 1, 2, 3 }
// 转回数组
const uniqueArr = [...uniqueSet];
console.log(uniqueArr); // [1, 2, 3]
// 简写
const uniqueArr2 = [...new Set(arr)];
Map(映射)
定义:Map 是一种键值对的集合,类似于对象,但键可以是任何类型。
特点:
- 键可以是任何类型(字符串、数字、对象、函数等)
- 保持插入顺序
- 有
size属性 - 迭代顺序与插入顺序一致
基本用法:
// 创建 Map
const map = new Map();
// 添加键值对
map.set('name', 'John');
map.set(1, 'one');
map.set(true, 'boolean');
map.set({ id: 1 }, 'object key');
// 获取值
console.log(map.get('name')); // 'John'
console.log(map.get(1)); // 'one'
// 检查键是否存在
console.log(map.has('name')); // true
// 删除键值对
map.delete('name');
// 获取大小
console.log(map.size); // 3
// 清空 Map
map.clear();
从数组创建 Map:
// 从二维数组创建
const entries = [
['name', 'John'],
['age', 30],
['city', 'Taipei'],
];
const map = new Map(entries);
console.log(map.get('name')); // 'John'
// 从对象创建
const obj = { name: 'John', age: 30 };
const map2 = new Map(Object.entries(obj));
console.log(map2.get('name')); // 'John'
2. Set vs Array
Set 与数组的差异
| 特性 | Set | Array |
|---|---|---|
| 重复值 | 不允许 | 允许 |
| 索引访问 | 不支持 | 支持 |
| 查找性能 | O(1) | O(n) |
| 插入顺序 | 保持 | 保持 |
| 常用方法 | add, has, delete | push, pop, indexOf |
使用场景:
// ✅ 适合使用 Set:需要唯一值
const userIds = new Set([1, 2, 3, 2, 1]);
console.log([...userIds]); // [1, 2, 3]
// ✅ 适合使用 Set:快速检查存在性
const visitedPages = new Set();
visitedPages.add('/home');
visitedPages.add('/about');
if (visitedPages.has('/home')) {
console.log('已访问过首页');
}
// ✅ 适合使用 Array:需要索引或重复值
const scores = [100, 95, 100, 90]; // 允许重复
console.log(scores[0]); // 100
3. Map vs Object
Map 与对象的差异
| 特性 | Map | Object |
|---|---|---|
| 键的类型 | 任何类型 | 字符串或 Symbol |
| 大小 | size 属性 | 需手动计算 |
| 默认键 | 无 | 有原型链 |
| 迭代顺序 | 插入顺序 | ES2015+ 保持插入顺序 |
| 性能 | 频繁增删较快 | 一般情况较快 |
| JSON | 不直接支持 | 原生支持 |
使用场景:
// ✅ 适合使用 Map:键不是字符串
const userMetadata = new Map();
const user1 = { id: 1 };
const user2 = { id: 2 };
userMetadata.set(user1, { lastLogin: '2024-01-01' });
userMetadata.set(user2, { lastLogin: '2024-01-02' });
console.log(userMetadata.get(user1)); // { lastLogin: '2024-01-01' }
// ✅ 适合使用 Map:需要频繁增删
const cache = new Map();
cache.set('key1', 'value1');
cache.delete('key1');
cache.set('key2', 'value2');
// ✅ 适合使用 Object:静态结构、需要 JSON
const config = {
apiUrl: 'https://api.example.com',
timeout: 5000,
};
const json = JSON.stringify(config); // 可直接序列化
4. Common Interview Questions
常见面试题目