Map 和 Set 是 ES6 引入的原生数据结构:Map 用于任意类型键的有序键值对映射,支持 get/set/has 等方法和 size 属性;Set 用于唯一值的有序集合,基于 SameValueZero 去重,适合存在性判断。

Map 和 Set 是 ES6 引入的两种原生数据结构,分别解决“键值对映射”和“唯一值集合”这两类常见需求。它们不是语法糖,而是有独立行为、方法和底层机制的构造器。
Map:键可以是任意类型的键值对容器
Map 本质是一个字典(dictionary),类似对象,但更灵活、更可靠:
- 键不限类型:数字、字符串、布尔、null、undefined、Symbol、函数、甚至整个对象或数组,都能当键;对象只能用字符串或 Symbol 作键
- 严格按插入顺序迭代:for...of 遍历时,元素顺序和 set() 顺序完全一致;普通对象属性顺序在早期 JS 中不保证,虽然后来规范有所收敛,但仍不如 Map 稳定
- 自带实用方法:get()、set()、has()、delete()、clear()、size 属性,操作直观;对象需靠 in、hasOwnProperty、Object.keys() + 循环等组合实现,不够直接
- 不把键自动转成字符串:new Map().set(1, 'a').set('1', 'b') 会存两个不同键;而 obj[1] = 'a'; obj['1'] = 'b' 实际只保留一个
Set:只存唯一值的有序集合
Set 是数学中“集合”的实现,核心是去重 + 快速查存在,不是数组的替代品:
本文档是python学习笔记与简明教程;为什么用Python作为编程入门语言?每种语言都会有它的支持者和反对者。去Google一下“why python”,你会得到很多结果,诸如应用范围广泛、开源、社区活跃、丰富的库、跨平台等等等等,也可能找到不少对它的批评,格式死板、效率低、国内用的人很少之类。不过这些优缺点的权衡都是程序员们的烦恼。作为一个想要学点编程入门的初学者来说,简单才是最重要的。当学C++的同学还在写链表,学Java的同学还在折腾运行环境的时候,学Pyt
- 值必须唯一:重复 add 同一个值(基于 SameValueZero 比较)不会生效;数组允许完全相同的元素多次出现
- 没有键的概念:Set 只有 value,value 就是 key;Map 和对象都有明确的键值分离
- 天然适合去重:[...new Set([1,2,2,3])] → [1,2,3];数组去重需 filter + indexOf 或 reduce,性能差且逻辑绕
- 支持对象引用去重:let a = {}, b = {}; new Set([a,a,b]) 只含两个元素;数组无法靠 === 自动识别相同引用
和对象(Object)比:Map 更适合做“数据映射”
对象本意是描述实体(如 user.name、config.timeout),不是通用键值存储工具。Map 才是为此设计的:
- 对象的 key 强制字符串化,容易误覆盖(比如 obj[true] = 1; obj[1] = 2 → 其实都写到 '1' 上)
- 对象不能直接获取键值对数量(得用 Object.keys(obj).length),Map 有现成的 size 属性
- 对象遍历要先取 keys 再取值,Map 可直接 for (let [k, v] of map) {},一步到位
- 动态增删大量键值对时,Map 的性能更稳定,尤其键为对象时
和数组(Array)比:Set 更适合“存在性判断”和“无序唯一集合”
数组强调顺序、索引、重复允许;Set 强调唯一、快速查找、无索引访问:
- 判断某值是否存在:Set.has(x) 是 O(1);数组要用 includes() 或 findIndex(),最坏 O(n)
- 合并多个唯一值列表:[...new Set([...a, ...b])] 比手动过滤简洁高效
- Set 不提供 push/pop/shift/unshift 等索引操作方法,也不支持通过下标访问,这点和数组有本质区别
- 两者都保持插入顺序,但 Set 不关心“第几个”,只关心“有没有”









