map中nan作为键时被视为相等,因使用samevaluezero算法(nan与自身相等),故多次set(nan)会覆盖而非新增,且不同来源的nan均被识别为同一键。

JavaScript 中 Map 的键使用的是“严格相等(SameValueZero)”算法来判断相等性,它与 === 基本一致,但有一个关键例外:NaN 被认为和自身相等。
Map 中 NaN 作为键的特殊行为
在普通比较中,NaN === NaN 返回 false,这是 IEEE 754 标准的规定。但 Map(以及 Set)内部使用 SameValueZero 算法,该算法规定:NaN 与任何 NaN 都视为相等 —— 包括它自己。
- 这意味着你可以用
NaN作为Map的键,并且后续用另一个NaN能正确查到它 -
Map不会把多个NaN键当作不同键重复存储
实际表现示例
看这段代码:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const map = new Map(); map.set(NaN, 'nan-value'); console.log(map.get(NaN)); // 'nan-value' ✅ console.log(map.size); // 1 map.set(NaN, 'new-nan'); console.log(map.size); // 还是 1 —— 覆盖了原值,不是新增
即使你用 Number.NaN、0/0、Math.sqrt(-1) 等不同方式生成的 NaN,它们在 Map 中都被视为同一个键。
和其他数据结构对比
这种行为和 Object 的属性名完全不同:对象属性名只能是字符串或 Symbol,NaN 会被转成字符串 "NaN";而 Map 保留原始类型,真正以 NaN 值为键。
-
Object:所有NaN都变成同名字符串键"NaN",无法区分 -
Map:用原始NaN值作键,SameValueZero 保证其一致性 -
Array.indexOf()等方法也用 SameValueZero,所以[NaN].indexOf(NaN)返回0
注意点:不是“唯一标识”,而是“值相等”
有人误以为 NaN 在 Map 中能当“唯一占位符”用,但要注意:只要值是 NaN,就匹配。它不记录来源、不区分类型(比如 Number.NaN 和 BigInt(0)/BigInt(0) 不行,因为后者抛错,但所有合法 NaN 均等价)。
- 不能靠
NaN键来存储多个独立的“未知值” - 若需区分,应改用唯一字符串(如
"unknown-1")、Symbol 或封装对象
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










