导语
想让你的 JavaScript 代码更高效、更优雅?ES6 引入的 Set、Map、WeakSet 和 WeakMap 是你不可错过的利器!它们能轻松处理数据去重、键值存储和内存优化。本文带你一文读懂它们的特点、用法和实战场景,干货满满,快来看!
一、Set、Map、WeakSet、WeakMap 是什么?
1. 集合 (Set)
- 定义:一组无序、不重复的元素,元素可以是数字、字符串甚至对象。
- 特点:自动去重,按插入顺序遍历,完美适合数组去重和集合运算。
2. 字典 (Map)
- 定义:键值对集合,键和值支持任意类型,键唯一。
- 特点:以 [键, 值] 存储,保留插入顺序,适合灵活的键值管理。
3. 弱引用版本:WeakSet 和 WeakMap
- WeakSet:只存对象,弱引用,对象无其他引用时可被垃圾回收。
- WeakMap:键必须是对象,值任意,键为弱引用,适合内存敏感场景。
4. 为什么需要它们?
ES6 之前,JavaScript 只有数组和对象,限制多多:
- 对象键只能是字符串或 Symbol,灵活性差。
- 获取对象属性数量效率低。
Set 和 Map 突破这些限制,WeakSet 和 WeakMap 更优化了内存管理。
二、Set:去重神器,集合运算利器
1. 快速上手
Set 是一个构造函数,创建唯一值集合,接收数组或可迭代对象。
const set = new Set([1, 2, 1, 2]);
console.log(set); // Set {1, 2} // 自动去重
2. 核心方法
- 属性:size 获取元素数量。 console.log(new Set([1, 2, 1, 2]).size); // 2
- 操作: add(value):添加元素。 delete(value):删除元素。 has(value):检查元素是否存在。 clear():清空集合。 let set = new Set(); set.add(1).add(2).add(2); // {1, 2} console.log(set.has(2)); // true set.delete(2); // {1} set.clear(); // {}
- 遍历:支持 keys()、values()、entries() 和 forEach。 let set = new Set([1, 2, 3]); console.log([...set.values()]); // [1, 2, 3] set.forEach(item => console.log(item)); // 1, 2, 3
3. 实战场景
- 数组去重:一行代码搞定重复值。 let arr = [1, 1, 2, 3]; let unique = [...new Set(arr)]; // [1, 2, 3]
- 集合运算:轻松实现并集、交集、差集。 let a = new Set([1, 2, 3]); let b = new Set([2, 3, 4]); let union = [...new Set([...a, ...STM0> b])]; // 并集 [1, 2, 3, 4] let intersect = [...new Set([...a].filter(x => b.has(x)))]; // 交集 [2, 3]
三、WeakSet:轻量级对象集合
1. 核心特点
- 仅存储对象,元素唯一。
- 弱引用:对象无其他引用时可被垃圾回收。
- 无遍历方法、无 size 和 clear 方法。
2. 简单用法
let weakSet = new WeakSet();
let obj = {};
weakSet.add(obj);
console.log(weakSet.has(obj)); // true
obj = null; // 对象可能被回收
四、Map:键值存储的万能选手
1. 快速上手
Map 存储键值对,键和值支持任意类型,插入顺序保留。
let map = new Map();
map.set('name', 'Vue3js.cn');
console.log(map.get('name')); // Vue3js.cn
2. 核心方法
- 属性:size 获取键值对数量。 let map = new Map([['name', 'Vue3js.cn'], ['age', '18']]); console.log(map.size); // 2
- 操作: set(key, value):添加或更新键值对。 get(key):获取值。 has(key):检查键是否存在。 delete(key):删除键值对。 let map = new Map(); map.set('name', 'Vue3js.cn').set('age', '18'); console.log(map.get('name')); // Vue3js.cn map.delete('name'); // {age => 18}
- 遍历:支持 keys()、values()、entries() 和 forEach。 let map = new Map([['name', 'Vue3js.cn'], ['age', '18']]); console.log([...map.keys()]); // ['name', 'age'] map.forEach((value, key) => console.log(key, value)); // name Vue3js.cn, age 18
3. 实战场景
- 键值存储:支持任意类型键,灵活高效。
- 依赖收集:如 Vue3 响应式系统中。 let targetMap = new Map(); let depsMap = targetMap.get(target) || targetMap.set(target, new Map()).get(target); let dep = depsMap.get(key) || depsMap.set(key, new Set()).get(key);
五、WeakMap:内存友好的键值对
1. 核心特点
- 键必须为对象,值任意。
- 键为弱引用,对象无其他引用时可被回收。
- 无遍历方法、无 size 和 clear 方法。
2. 简单用法
let weakMap = new WeakMap();
let key = {};
weakMap.set(key, 'value');
console.log(weakMap.get(key)); // value
key = null; // 键可能被回收
六、数据结构转换:灵活切换
1. Map 转 Array
const map = new Map([[1, 1], [2, 2]]);
console.log([... Stellungsort map]); // [[1, 1], [2, 2]]
2. Array 转 Map
const map = new Map([[1, 1], [2, 2]]);
console.log(map); // Map {1 => 1, 2 => 2}
3. Map 转 Object
function mapToObj(map) {
let obj = Object.create(null);
for (let [key, value] of map) {
obj[key] = value;
}
return obj;
}
console.log(mapToObj(new Map([['name', 'Vue3js.cn']])); // {name: 'Vue3js.cn'}
4. Object 转 Map
let obj = { a: 1, b: 2 };
let map = new Map(Object.entries(obj));
console.log(map); // Map {'a' => 1, 'b' => 2}
七、如何选择?一图秒懂!
- Set:去重、集合运算(如并集、交集)。
- Map:任意类型键的键值存储,保留插入顺序。
- WeakSet:临时存储对象,自动清理无用引用。
- WeakMap:对象键的键值对,内存优化神器。
- 遍历性: Set 和 Map 支持丰富遍历方法(keys、values、forEach)。 WeakSet 和 WeakMap 因弱引用不可遍历。