面试官 : “ 说一下 Map 和 WeakMap 的区别 ? ”

一、Map vs WeakMap

特性 Map WeakMap
键的类型 任意类型(基本类型 / 引用类型) 仅支持引用类型(对象)
键的引用特性 强引用:键对象不会被 GC 回收 弱引用:键对象无其他引用时,会被 GC 自动回收(键值对随之消失)
遍历性 支持(keys ()/values ()/entries ()/forEach/for...of) 不支持(无遍历方法、无 size 属性)
键的枚举 / 获取 可获取所有键(如 Array.from (map.keys ())) 无法获取 / 枚举所有键(无 API)
常用 API set/get/has/delete/clear/size set/get/has/delete(无 clear/size)
内存占用 键对象未手动删除则一直占用 自动回收无引用的键,内存更友好
使用场景 需遍历 / 枚举、键为基本类型、长期存储键值对 临时关联数据(如 DOM 元素→元数据)、避免内存泄漏

核心差异:弱引用

  • Map 对键是强引用:即使键对象外部无引用,Map 仍持有该对象,GC 不会回收,可能导致内存泄漏;
  • WeakMap 对键是弱引用:键对象仅被 WeakMap 引用时,GC 会回收该对象,同时 WeakMap 中对应的键值对也会被移除(无需手动删除)。

示例

ini 复制代码
// Map:强引用导致内存泄漏风险
const map = new Map();
let obj = { id: 1 };
map.set(obj, "data");
obj = null; // 手动置空,但map仍引用obj,GC不会回收

// WeakMap:弱引用自动回收
const weakMap = new WeakMap();
let obj2 = { id: 2 };
weakMap.set(obj2, "data");
obj2 = null; // obj2无其他引用,GC回收后,weakMap中该键值对消失

二、Set vs WeakSet

特性 Set WeakSet
值的类型 任意类型(基本类型 / 引用类型) 仅支持引用类型(对象)
值的引用特性 强引用:值对象不会被 GC 回收 弱引用:值对象无其他引用时,会被 GC 自动回收(值随之移除)
遍历性 支持(keys ()/values ()/entries ()/forEach/for...of) 不支持(无遍历方法、无 size 属性)
值的枚举 / 获取 可获取所有值(如 Array.from (set)) 无法获取 / 枚举所有值(无 API)
常用 API add/has/delete/clear/size add/has/delete(无 clear/size)
内存占用 值对象未手动删除则一直占用 自动回收无引用的值,内存更友好
使用场景 需遍历 / 枚举、值为基本类型、存储唯一值集合 存储临时对象(如 DOM 元素集合)、避免内存泄漏

核心差异:弱引用

  • Set 对值是强引用:值对象即使外部无引用,Set 仍持有,GC 不回收;
  • WeakSet 对值是弱引用:值对象仅被 WeakSet 引用时,GC 会回收该对象,WeakSet 中对应的项也会被移除。

示例

ini 复制代码
// Set:强引用
const set = new Set();
let obj = { id: 1 };
set.add(obj);
obj = null; // set仍引用obj,GC不回收

// WeakSet:弱引用
const weakSet = new WeakSet();
let obj2 = { id: 2 };
weakSet.add(obj2);
obj2 = null; // obj2无其他引用,GC回收后,weakSet中该值消失

三、Map vs Set 区别(补充知识)

Map 和 Set 都是 ES6 新增的有序集合(迭代顺序为插入顺序) ,均为强引用、支持遍历、可存储唯一值,但核心定位和数据结构完全不同,以下是详细对比:

特性 Map Set
核心定位 键值对集合(键→值映射) 值的集合(仅存储唯一值,无键)
存储形式 [key, value] 键值对,键唯一、值可重复 单个值(value),值必须唯一
重复判定规则 键唯一(NaN 视为相同,对象引用不同则视为不同) 值唯一(规则同 Map 键的判定)
核心 API(增) set(key, value):按键存值 add(value):添加值
核心 API(查) get(key):按键取值;has(key):判断键是否存在 has(value):判断值是否存在(无 get
核心 API(删) delete(key):按键删除键值对 delete(value):按值删除项
遍历方式 可遍历键(keys())、值(values())、键值对(entries() 可遍历值(keys()/values() 等价,entries() 返回 [value, value]
长度 / 大小 size 属性:返回键值对数量 size 属性:返回唯一值数量
使用场景 1. 键值映射(如 ID→用户信息)2. 需要通过 "键" 快速查找 "值"3. 存储关联数据 1. 存储不重复的唯一值集合(如去重数组)2. 仅需判断 "值是否存在"3. 过滤重复数据

1. Map:键值对存储与查找

c 复制代码
const map = new Map();
// 存:键唯一,值可重复
map.set("id1", { name: "张三" });
map.set("id2", { name: "李四" });
map.set("id1", { name: "张三2" }); // 覆盖id1的旧值

// 查:按键取值
console.log(map.get("id1")); // { name: "张三2" }
console.log(map.has("id2")); // true

// 遍历:键、值、键值对
for (const key of map.keys()) console.log(key); // id1、id2
for (const value of map.values()) console.log(value); // {name: "张三2"}、{name: "李四"}
for (const [k, v] of map.entries()) console.log(k, v);

2. Set:唯一值集合(无键)

csharp 复制代码
const set = new Set();
// 存:值唯一,重复添加无效
set.add(1);
set.add(2);
set.add(1); // 无效果,1已存在

// 查:仅能判断值是否存在,无get
console.log(set.has(2)); // true
// console.log(set.get(2)); // 报错:Set 无get方法

// 遍历:keys/values等价,entries返回[值, 值]
for (const val of set.values()) console.log(val); // 1、2
for (const [v1, v2] of set.entries()) console.log(v1, v2); // 1 1、2 2

// 典型场景:数组去重
const arr = [1, 2, 2, 3];
const uniqueArr = [...new Set(arr)]; // [1,2,3]

3.核心总结

维度 Map Set
数据结构 键值对(字典) 单值集合(集合)
核心操作 按 "键" 存 / 取 / 删 按 "值" 增 / 判 / 删(无取值操作)
重复处理 键唯一(值可重复) 值唯一(无重复)
核心用途 键值映射、关联数据存储 去重、唯一值判断

简单记:

  • 需要 "通过一个标识找对应数据"→ 用 Map;
  • 只需要 "存储不重复的一组值,或判断值是否存在"→ 用 Set。

三、通用总结

类型 核心特点 适用场景
Map/Set 强引用、支持遍历、键 / 值可存任意类型 需持久存储、遍历、键 / 值为基本类型的场景
WeakMap/WeakSet 弱引用、不支持遍历、仅存引用类型 临时关联数据、避免内存泄漏(如 DOM / 临时对象)

关键提醒

WeakMap/WeakSet 无法遍历 / 获取 size,因为其内部数据会被 GC 动态修改,无法保证数据的稳定性;

而 Map/Set 是 "可预测" 的静态集合(除非手动修改)。

相关推荐
C雨后彩虹2 小时前
二维伞的雨滴效应
java·数据结构·算法·华为·面试
2501_924064112 小时前
2025年主流Web自动化测试工具功能与适用场景对比
前端·测试工具·自动化
可触的未来,发芽的智生2 小时前
一万个为什么:频率和相位
javascript·人工智能·python·程序人生·自然语言处理
IT_陈寒2 小时前
Vite 5 实战:7个鲜为人知的配置技巧让构建速度提升200%
前端·人工智能·后端
gg159357284602 小时前
JavaScript 核心基础
前端·javascript·vue.js
Stanford_11062 小时前
【2026新年启程】学习之路,探索之路,技术之路,成长之路……都与你同行!!!
前端·c++·学习·微信小程序·排序算法·微信开放平台
打小就很皮...2 小时前
网页包装为桌面应用(Nativefier版)
前端·桌面应用·nativefier
拾荒李3 小时前
性能优化-手搓定高虚拟列表实现
javascript·性能优化
自由生长20243 小时前
为什么我们需要流式系统?
前端