JavaScript Map 和 Set 教程
Map 数据结构
Map 基本概念
Map 是一种键值对的集合,类似于对象(Object),但是它的键可以是任何数据类型(包括对象、函数等),而不仅限于字符串。Map 提供了一系列方法来操作这些键值对。
Map 的创建和基本操作
// 创建空 Map
const map = new Map();
// 使用数组创建 Map
const map2 = new Map([
['name', '张三'],
['age', 25]
]);
// 添加键值对
map.set('key1', 'value1');
map.set(true, 123);
map.set({x: 1}, 'object as key');
// 获取值
console.log(map.get('key1')); // 'value1'
// 检查键是否存在
console.log(map.has('key1')); // true
// 删除键值对
map.delete('key1');
// 获取 Map 大小
console.log(map.size);
// 清空 Map
map.clear();
Map 的遍历方法
const map = new Map([
['name', '张三'],
['age', 25],
['city', '北京']
]);
// 遍历所有键值对
map.forEach((value, key) => {
console.log(`${key}: ${value}`);
});
// 获取所有键
for (let key of map.keys()) {
console.log(key);
}
// 获取所有值
for (let value of map.values()) {
console.log(value);
}
// 获取所有键值对
for (let [key, value] of map.entries()) {
console.log(`${key}: ${value}`);
}
Map 与对象的区别
- 键的类型:Map 的键可以是任何类型,Object 的键只能是字符串或 Symbol
- 键的顺序:Map 会维护键值对的插入顺序,Object 不保证顺序
- Size:Map 可以直接获取 size 属性,Object 需要手动计算
- 迭代:Map 可直接迭代,Object 需要先获取键数组
Set 数据结构
Set 基本概念
Set 是一种值的集合,其中的值都是唯一的。它类似于数组,但成员的值都是唯一的,没有重复的值。
Set 的创建和基本操作
// 创建空 Set
const set = new Set();
// 使用数组创建 Set
const set2 = new Set([1, 2, 3, 3, 4]); // 重复值会被自动去除
// 添加值
set.add(1);
set.add('text');
set.add({x: 10});
// 检查值是否存在
console.log(set.has(1)); // true
// 删除值
set.delete(1);
// 获取 Set 大小
console.log(set.size);
// 清空 Set
set.clear();
Set 的遍历方法
const set = new Set(['A', 'B', 'C']);
// forEach 遍历
set.forEach(value => {
console.log(value);
});
// for...of 遍历
for (let item of set) {
console.log(item);
}
// 获取所有值
for (let value of set.values()) {
console.log(value);
}
// 获取所有键(与值相同)
for (let key of set.keys()) {
console.log(key);
}
// 获取所有键值对(键和值相同)
for (let [key, value] of set.entries()) {
console.log(key, value);
}
Set 的常用应用场景
- 数组去重
const array = [1, 2, 2, 3, 3, 4];
const uniqueArray = [...new Set(array)];
console.log(uniqueArray); // [1, 2, 3, 4]
- 并集、交集和差集操作
const setA = new Set([1, 2, 3]);
const setB = new Set([2, 3, 4]);
// 并集
const union = new Set([...setA, ...setB]);
// 交集
const intersection = new Set([...setA].filter(x => setB.has(x)));
// 差集
const difference = new Set([...setA].filter(x => !setB.has(x)));
性能考虑
Map 的性能优势
- 频繁增删键值对场景下,Map 比 Object 性能更好
- 键值对数量很大时,Map 的增删改查性能更优
Set 的性能优势
- 检查值是否存在的性能比数组好
- 处理大量数据去重时性能优于数组方法
最佳实践建议
- 选择使用 Map 的场景:
- 键需要是非字符串类型
- 需要频繁增删键值对
- 需要维护插入顺序
- 需要频繁获取大小
- 选择使用 Set 的场景:
- 需要存储唯一值集合
- 需要频繁检查值是否存在
- 需要数组去重
- 需要集合运算(并集、交集、差集)
- 注意事项:
- Map 和 Set 都不能序列化为 JSON
- WeakMap 和 WeakSet 适用于需要垃圾回收的场景
- 考虑浏览器兼容性,需要时使用 polyfill