推荐答案
WeakMap 和 Map 的主要区别在于:
键的类型:
- Map 的键可以是任意类型的值(包括对象、原始值等)。
- WeakMap 的键只能是对象(即引用类型),不能是原始值。
垃圾回收:
- Map 中的键是强引用的,即使键对象在其他地方没有被引用,Map 仍然会持有该对象的引用,阻止其被垃圾回收。
- WeakMap 中的键是弱引用的,如果键对象在其他地方没有被引用,WeakMap 不会阻止垃圾回收机制回收该对象。
可枚举性:
- Map 是可枚举的,可以通过
for...of
或forEach
等方法遍历其键值对。 - WeakMap 是不可枚举的,无法直接遍历其键值对。
- Map 是可枚举的,可以通过
API 差异:
- Map 提供了丰富的 API,如
size
属性、keys()
、values()
、entries()
等方法。 - WeakMap 的 API 较为有限,仅支持
set()
、get()
、has()
和delete()
方法。
- Map 提供了丰富的 API,如
本题详细解读
1. 键的类型
Map:Map 的键可以是任意类型的值,包括对象、字符串、数字等。例如:
const map = new Map(); map.set('key1', 'value1'); // 字符串作为键 map.set({}, 'value2'); // 对象作为键
WeakMap:WeakMap 的键只能是对象,不能是原始值。例如:
const weakMap = new WeakMap(); const obj = {}; weakMap.set(obj, 'value'); // 对象作为键 // weakMap.set('key1', 'value1'); // 报错,原始值不能作为键
2. 垃圾回收
Map:Map 中的键是强引用的,即使键对象在其他地方没有被引用,Map 仍然会持有该对象的引用,阻止其被垃圾回收。例如:
let obj = { key: 'value' }; const map = new Map(); map.set(obj, 'data'); obj = null; // obj 不再被引用,但 Map 仍然持有其引用,obj 不会被垃圾回收
WeakMap:WeakMap 中的键是弱引用的,如果键对象在其他地方没有被引用,WeakMap 不会阻止垃圾回收机制回收该对象。例如:
let obj = { key: 'value' }; const weakMap = new WeakMap(); weakMap.set(obj, 'data'); obj = null; // obj 不再被引用,WeakMap 不会阻止其被垃圾回收
3. 可枚举性
Map:Map 是可枚举的,可以通过
for...of
或forEach
等方法遍历其键值对。例如:const map = new Map(); map.set('key1', 'value1'); map.set('key2', 'value2'); for (const [key, value] of map) { console.log(key, value); // 输出键值对 }
WeakMap:WeakMap 是不可枚举的,无法直接遍历其键值对。例如:
const weakMap = new WeakMap(); const obj = {}; weakMap.set(obj, 'value'); // for (const [key, value] of weakMap) { // 报错,WeakMap 不可枚举 // console.log(key, value); // }
4. API 差异
Map:Map 提供了丰富的 API,如
size
属性、keys()
、values()
、entries()
等方法。例如:const map = new Map(); map.set('key1', 'value1'); console.log(map.size); // 输出 1 console.log([...map.keys()]); // 输出 ['key1']
WeakMap:WeakMap 的 API 较为有限,仅支持
set()
、get()
、has()
和delete()
方法。例如:const weakMap = new WeakMap(); const obj = {}; weakMap.set(obj, 'value'); console.log(weakMap.has(obj)); // 输出 true console.log(weakMap.get(obj)); // 输出 'value' weakMap.delete(obj); console.log(weakMap.has(obj)); // 输出 false