推荐答案
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