前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库Map size 与对象键数量获取
JavaScript数组与集合

Map.size 和 Object.keys(obj).length 数的到底是什么?

Map.size 直接告诉你有多少个条目,更新已有键不会增加。普通对象没有现成的数量属性,Object.keys(obj).length 只数自己的、可枚举的字符串键,Symbol 键和不可枚举属性都不算。数组的 length 又是另一回事,它是最大索引加一。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#数组与集合
先看核心答案读代码示例
理解线索

三个数字,三种范围

  1. map.sizeset 和 delete 管理的条目数,随时是最新的
  2. Object.keys(obj).length对象自己的、可枚举的字符串键,每次调用都要生成数组
  3. arr.length最大索引加一,稀疏数组里可能大于实际元素数

size 是只读的访问器属性,给它赋值不会清空 Map,严格模式下还会报错。清空要用 clear()。

核心回答

先记住这个答案

Map.size 表示当前有多少个键值条目,set 一个新键加 1,delete 成功减 1,更新已有键的值数量不变。给 Map 对象挂的普通属性不算条目,也不计入 size。普通对象没有自动维护的数量属性,常用 Object.keys(obj).length,但它只统计对象自己的、可枚举的、字符串类型的键。要把 Symbol 键和不可枚举属性也算进去,用 Reflect.ownKeys(obj).length。数组的 length 是最大索引加一,稀疏数组里它会大于实际元素个数。

  • Map.size 数条目,给 Map 挂的普通属性不算
  • Object.keys 只数自有、可枚举的字符串键
  • 数全部自有键用 Reflect.ownKeys
  • 数组 length 是最大索引加一,不等于元素个数

同一组操作,不同的计数结果

下面分别看 Map、带特殊属性的对象和稀疏数组,三种计数方式各自数到了什么。

三种计数方式JavaScript
const map = new Map([['a', 1]])
map.set('a', 2)                    // 更新已有键
map.note = 'debug'                 // 挂一个普通属性
console.log(map.size, Object.keys(map).length)

const object = { visible: 1 }
Object.defineProperty(object, 'hidden', { value: 2 })  // 不可枚举
object[Symbol('tag')] = 3                               // Symbol 键
console.log(Object.keys(object).length, Reflect.ownKeys(object).length)

console.log(new Array(4).length, Object.keys(new Array(4)).length)
查看输出与解释
1 1
1 3
4 0

第一行两个 1 来源完全不同。map.size 的 1 是条目 'a',更新值没有让它变成 2;Object.keys(map) 的 1 是 note 这个普通属性,它根本看不到条目。第二行 Object.keys 只数到了 visible,而 Reflect.ownKeys 连不可枚举的 hidden 和 Symbol 键都数到了。第三行是长度为 4 但一个元素都没有的稀疏数组。

普通对象为什么没有 length

length 不是对象的通用能力。数组有 length,是因为数组对它做了特殊处理,添加索引时会自动更新。普通对象读 obj.length,只是在读一个叫 length 的普通属性,没有定义过就是 undefined。

选哪种统计方式
配置面板显示「共几个字段」,通常只关心用户看得见的字段,Object.keys 就合适。做深度比较、复制工具这类需要完整反射的场景,才需要 Reflect.ownKeys。for...in 也能数,但它会把原型链上可枚举的属性一起算进去,要配合 Object.hasOwn 过滤。 另外,Object.keys 每次调用都会生成一个新数组。在高频循环里反复统计一个大对象的键数,开销不小。数据本来就是频繁增删的键值集合时,直接用 Map,读 size 不需要额外开销。
回答前,多想一步

容易答错的地方

用 obj.length 统计属性个数
普通对象的 length 就是一个普通属性,不会随着添加删除属性自动变化。统计属性个数要用 Object.keys 或 Reflect.ownKeys。
给 size 赋 0 来清空 Map
size 定义在 Map.prototype 上,只有读取函数,没有写入函数。非严格模式下 map.size = 0 静默失败,严格模式下抛 TypeError,条目一个都没删。清空用 map.clear()。
试着用自己的话回答

面试官还会怎么问?

Set 有 size 吗?WeakMap 呢?

Set 有,含义和 Map 一样,是成员个数。WeakMap 和 WeakSet 没有 size,也不能遍历,因为它们的成员可能随时被垃圾回收,给出一个确定的数字就等于暴露了回收时机。

Object.keys 返回的键包含 Symbol 吗?

不包含。只要 Symbol 键可以用 Object.getOwnPropertySymbols,要全部自有键用 Reflect.ownKeys,它会同时返回字符串键和 Symbol 键,包括不可枚举的。

怎么统计数组里真正有多少个元素?

稠密数组直接用 length。可能有空位的数组,用 Object.keys(arr).length 数实际存在的索引,或者 arr.filter(() => true).length,因为 filter 会跳过空位。

从一道题,走向一组知识

把知识连起来

数组与集合

用普通对象当字典时为什么会读到原型属性,Map 能避免吗?

Object.keys 只数自有属性,而读属性会查原型链,两篇合起来能分清对象字典的读取和统计范围。

数组与集合

频繁判断元素是否存在时,Set.has 一定比 includes 快吗?

Object.keys 每次都要生成数组,频繁统计时的开销和那篇讨论的建索引成本是同一类问题。

数组与集合

WeakMap 的键只能是对象吗,它怎样影响垃圾回收?

WeakMap 没有 size,那篇讲它为什么故意不提供计数和遍历。

参考资料

  • MDN:Map.size
  • MDN:Reflect.ownKeys

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 同一组操作,不同的计数结果
  3. 普通对象为什么没有 length
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑