map 的 size 属性访问是 o(1),直接返回内部计数器;object.keys().length 是 o(n),需遍历枚举属性并创建数组,且漏统计不可枚举属性和 symbol 键,语义与性能均劣于 map。

Map 的 size 是一个原生属性,访问是 O(1) 时间复杂度,直接返回内部计数器值,不触发遍历或计算。
Object.keys().length 需要实际执行三步操作
它必须:
- 调用
Object.keys()—— 创建一个新数组,枚举所有可枚举的自有属性键(跳过不可枚举属性、Symbol 键、原型链上的键) - 该过程涉及哈希表遍历和数组分配,时间复杂度为 O(n)
- 再取数组的
length属性 —— 这步虽快,但前面的开销已不可忽略
实际影响场景
在高频读取长度的代码中(如循环内判断、缓存命中检查、LRU 驱逐逻辑),差异明显:
- 10 万条键值对的 Map:每次
map.size耗时基本恒定,约 0.001ms 级别 - 同量级 Object:每次
Object.keys(obj).length可能达 0.5–2ms,且随数据量线性增长 - 若对象有大量不可枚举属性或 Symbol 键,
Object.keys()还会漏统计,导致语义错误
更可靠的替代方案(如果非用 Object 不可)
想接近 Map 的效率,可自行维护一个计数器:
- 增删属性时同步更新
obj._size = obj._size + 1或-1 - 但需严格保证操作路径唯一(避开
delete obj.k、Reflect.deleteProperty等遗漏点) - 不如直接用 Map 简洁安全
所以不是“稍快一点”,而是设计层级的差异:size 是状态,keys().length 是推导结果。











