map的键名支持任意原始类型且按samevaluezero算法比较:字符串/数字/布尔值按值相等(0与-0相同,"1"与1不同);undefined、null独立存在;symbol每次调用唯一,symbol.for可复用;bigint与数字类型不同;nan被视为自等。

JavaScript中,Map的键名可以是任意类型,包括原始类型(如字符串、数字、布尔值、undefined、null、Symbol、BigInt),但它们在Map内部的比较逻辑与对象不同——原始类型按值相等(===)判断,而非引用相等。这意味着相同值的原始类型会映射到同一个键,这是它和Object键名(自动转为字符串)的关键区别。
字符串、数字、布尔值:值相等即同一键
这些类型直接按字面值比较。例如:
-
map.set("1", "a")和map.set(1, "b")是两个独立键,因为"1" !== 1; -
map.set(0, "zero")和map.set(-0, "minusZero")实际上是同一个键,因为0 === -0为 true(ES6 Map 明确规定-0和0视为相同键); -
map.set(true, "yes")和map.set(!false, "also yes")也指向同一位置,因为表达式结果都是true。
undefined 和 null:各自独立,且不被强制转换
它们不会像在Object中那样被转成字符串 "undefined" 或 "null",而是作为原生值存在:
-
map.set(undefined, "missing")和map.set(null, "empty")是两个不同的键; -
map.get(undefined)只能取到用undefined设置的值,不会误匹配null或"undefined"字符串; - 注意:Map允许
undefined作为键,这和Object中obj[undefined]等价于obj["undefined"]完全不同。
Symbol 和 BigInt:严格唯一性保障
这两类原始类型天然适合做精确键名:
- 每个
Symbol()都是唯一值,即使描述相同:Symbol("a") !== Symbol("a"),所以每次调用都会创建新键; -
Symbol.for("a") === Symbol.for("a"),这种全局注册的Symbol可跨地方复用为同一键; - BigInt 支持大整数作键,且
1n === 1n,但1n !== 1,类型不同即不同键,避免隐式转换歧义。
NaN 的特殊行为:被视为相等
尽管 NaN !== NaN 是 JavaScript 的基本规则,但 Map 在内部使用 SameValueZero 算法判断键相等性,该算法将 NaN 视为与自身相等:
-
map.set(NaN, "not a number")后,map.get(NaN)能正确返回该值; - 多次用
NaN设键,实际只保留一个; - 这和
Array.prototype.indexOf()或Set中对NaN的处理一致,是规范明确设计的行为。
Map 对原始类型键的支持干净、可预测,没有隐式类型转换,也没有意外的字符串化,是替代“伪哈希对象”的可靠选择。只要记住它用 SameValueZero 判断相等(即 === 的变体,仅对 NaN 特殊处理),就能准确预期各种原始值的表现。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











