ES6 Map的键名支持任意数据类型,因其不字符串化键、用Object.is()判断相等性、底层哈希表适配多类型键值且无原型链干扰。

ES6 Map 的键名能支持任意数据类型,核心在于它不依赖属性名字符串化机制,而是用内部哈希表配合 Object.is() 算法做键比较,同时为不同类型的键值分别维护内存引用或值语义判断。
底层不把键转成字符串
传统对象(Object)在设置属性时,会自动调用 toString() 把非字符串键转为字符串。比如:const obj = {}; obj[{}]=1; obj[{}]=2;
两个空对象都变成 "[object Object]",最终只保留一个属性。
Map 完全绕过这一步——它直接拿原始值(数字、布尔、对象、NaN、函数等)参与哈希计算和查找,不强制类型转换。
键的相等性由 Object.is() 决定
Map 判断“两个键是否相同”,用的是 Object.is(a, b),而不是 == 或 ===。这意味着:
-
0和-0被视为相等(Object.is(0, -0)返回false,但 Map 特殊处理,将二者统一视为同一键) -
NaN和NaN相等(Object.is(NaN, NaN) === true,所以多次设map.set(NaN, 'a')不会新增条目) - 对象键必须是同一个引用:两个字面量对象
{}和{}地址不同,算作两个独立键 - 基本类型键按值比较:
map.set(5, 'a')和map.set('5', 'b')是两个键,因为Object.is(5, '5') === false
内部哈希表适配多种键类型
Map 的实现不是靠对象属性模拟,而是用原生引擎级哈希结构(如 V8 中的 HashTable 或 OrderedHashTable),针对不同键类型做差异化处理:
- 对原始值(number/string/boolean/Symbol/undefined/null),直接参与哈希码计算
- 对引用类型(Object/Array/Function),使用其内存地址(identity hash)作为哈希依据
- 对
NaN这类特殊值,有单独标记逻辑,确保多次插入不重复
这种设计让 Map 在保持 O(1) 平均查找性能的同时,彻底摆脱了字符串键的限制。
没有原型链干扰,键名无隐式污染
Object 的属性查找会沿原型链向上找,比如 obj.toString 可能来自 Object.prototype;而 Map 的键完全隔离,map.has('toString') 只检查你显式 set 过的键,不会受任何原型方法影响。这也让它更安全、语义更干净。


















