JavaScript Map与Object怎么选_键值类型有何限制?

12次阅读

Object键只能是字符串symbol,其他类型会转为字符串导致冲突;map支持任意类型键且不转换,适合缓存等场景。

JavaScript Map与Object怎么选_键值类型有何限制?

Object 的键只能是字符串或 Symbol

javaScript 中 Object 的键会自动转为字符串(除了 Symbol),哪怕你写 { [1]: 'a' },实际也是 { '1': 'a' }。数组、对象、函数等作为键时,统统调用 toString(),结果往往是 '[object Object]',导致意外覆盖:

const obj = {}; obj[{}] = 'first'; obj[{}] = 'second'; console.log(Object.keys(obj)); // ['[object Object]'] console.log(obj[{}]); // 'second' —— 前一个被覆盖了

Symbol 是唯一能避免自动转换的例外,但每个 Symbol() 都是唯一值,无法复用作通用键。

Map 允许任意类型作键,包括 NULL、NaN、对象、函数

Map 不做类型转换,键的相等性基于 SameValueZero 算法NaNNaN 视为相等,这点和 === 一致):

  • map.set({}, 'obj1')map.set({}, 'obj2') 是两个独立条目
  • map.set(NaN, 'nan') 可以正确存取,map.get(NaN) 返回 'nan'
  • map.set(null, 'null')map.set(undefined, 'undef') 都合法且互不干扰

这使得 Map 天然适合缓存、元数据绑定、事件监听器映射等场景——比如把 dom 元素当键存其对应配置,不用担心元素被回收或键冲突。

立即学习Java免费学习笔记(深入)”;

性能与迭代顺序:Map 更稳定,Object 有隐式排序规则

Map 严格按插入顺序迭代,行为确定;Object 的属性遍历顺序虽在 ES2015 后也规定为插入顺序,但存在例外:

  • 纯数字字符串键(如 '1''2''10')会被按数值大小排序,而非插入顺序
  • 负号开头的数字字符串(如 '-1')会被当作普通字符串处理
  • Symbol 键总在最后

例如:

const obj = { '2': 'b', '10': 'j', '1': 'a' }; console.log(Object.keys(obj)); // ['1', '2', '10'] —— 数值排序,不是插入顺序

Map 没有这类陷阱,map.forEachfor...of 总是按写入顺序执行。

什么时候该用 Object,什么时候必须用 Map?

Object 当:

  • 键固定且已知是字符串(如配置项 { timeout: 5000, retry: 3 }
  • 需要原型方法(hasOwnPropertyisPrototypeOf)或与 jsON 互转(json.stringify 不处理 Map
  • 用点语法或方括号访问更自然(obj.namemap.get('name') 少打几个字符)

必须用 Map 当:

  • 键可能为非字符串(对象、函数、nullNaN
  • 需要频繁增删键值对Mapdelete 是 O(1),而 delete obj[key] 在某些引擎中可能触发哈希表重建)
  • 依赖精确的插入顺序迭代(尤其涉及数字字符串键时)
  • 要获取键值对数量(map.size 是属性,Object.keys(obj).Length 需生成新数组)

键类型限制不是“能不能用”的问题,而是“会不会意外丢失语义”的问题。一旦你发现某个逻辑里想用 {}function 当键,就别犹豫,直接上 Map

text=ZqhQzanResources