← 返回目录

10. Set 和 Map

Set 是不重复值的集合,Map 是键可以是任意类型的对象

核心两个:
Set——自动去重,new Set([1,1,2]) 得 {1,2}
Map——键可以是对象,Map.get(key) / Map.set(key, val)

坑:Set 去重 NaN 也能去、Map 比对象灵活(键不限字符串)、都要用 size 不是 length

10.1 互动演示

点按钮看 Set / Map 的实际行为。

10.2 知识点讲解

一、Set:自动去重的袋子

① 以前去重要写循环,现在一行

以前去重得写一个空数组,遍历原数组,每看到一个新值才 push 进去——啰嗦。new Set(数组) 自动去重,再用 [...] 展开回数组,一行搞定。

// 有重复的数组
let arr = [1, 2, 3, 4, 4, 3];

// 以前:循环 + indexOf 判断,啰嗦
// 先开个空数组
let unique = [];

// 挨个遍历
arr.forEach(x => {

// 没见过才加
  if (unique.indexOf(x) === -1) unique.push(x);

// 现在:new Set 自动去重 + ... 展开回数组
});

// Set 自动去重,... 再拆回数组
let unique = [...new Set(arr)];

// ^^^ 把 Set 重新拆成数组
// [1,2,3,4]
console.log(unique);

new Set(数组) 自动去重,[...set] 再变回数组。这是最常用的数组去重写法,面试必背

② Set 常用方法

往袋子里扔(add)、拿出来看有没有(has)、扔掉一个(delete)、倒空(clear)、数个数(size)。

// 开个空袋子
let s = new Set();

// 扔进去
s.add("大哥");

// 再扔一个
s.add("二哥");

// 重复的扔不进去,袋子自动忽略
s.add("大哥");

// 2(袋子里现在有几个)
s.size;

// true(有没有这个)
s.has("大哥");

// 扔掉一个 → true
s.delete("二哥");

// 整个袋子倒空
s.clear();

二、Map:钥匙随便的"加强版对象"

③ 普通对象的键会被转成字符串

普通对象有个坏习惯:你拿数字当钥匙,它偷偷帮你转成字符串;想拿对象当钥匙?门都没有。Map 不转类型,钥匙原样保留。

// 普通对象:键强制转字符串
// 普通对象
let obj = {};

// 拿数字 123 当键
obj[123] = "数字键";

// {"123": "数字键"} ← 123 被转成 "123" 了
console.log(obj);

// Map:键保持原样,对象也能当键
// 开个 Map
let m = new Map();

// 数字键
m.set(123, "数字键");

// 对象当键,普通对象做不到!
m.set({ id: 1 }, "对象键");

// 数字键
console.log(m.get(123));

Map 的键可以是数字、对象、数组,不会像普通对象那样被强制转成字符串。动态增删键值对、需要用对象/数字当 key 的场景,用 Map 最合适。

④ Map 常用方法

// 开个空 Map
let m = new Map();

// 放一对键值
m.set("name", "大喇叭");

// 拿值 → 大喇叭
m.get("name");

// 有没有 → true
m.has("name");

// 删掉一对 → true
m.delete("name");

// 有几对
m.size;

// 全清空
m.clear();

⑤ 普通对象 vs Map

对比项普通对象Map
键的类型只能字符串 / 符号任意类型(数字、对象都行)
遍历for...in 比较绕forEach 直接遍历,按插入顺序
常用场景字段固定的数据(如 User)动态增删的键值对

10.3 实战:用在哪 / 常见坑 / 怎么解决

① 可能在什么地方用:数组去重 [...new Set(arr)]、两个数组求交集/并集、用对象当 key 存关联数据、记录用户访问过的页面。

② 常见的问题:把 Set 当数组直接用 arr[i] 取下标(Set 没有下标);用普通对象存对象键导致 key 全变字符串;遍历 Map 用 for...in 遍历不到。

③ 解决思路:Set 要取下标就先 [...set] 展开;Map 用 m.forEachfor...of m;需要对象键就用 Map,别用普通对象。

一句话:Set 管"不重复",Map 管"任意键";去重用 [...new Set(arr)]

本页重点

API作用参数返回值代码示例
new Set(arr)把数组扔进自动去重的袋子可遍历对象一个 Setnew Set([1, 1, 2]);
.has(x)判断袋子里有没有某项要查的值true / falseset.has(1);
new Map()键可以是数字、对象等任意类型的字典-一个 Mapnew Map();
.set(k, v)存一个键值对键, 值这个 Mapmap.set("a", 1);
.get(k)按键取值对应的值map.get("a");