前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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 热点
旧版
首页程序员面试题库Reflect.ownKeys 键顺序 与 Object.keys 区别
JavaScript对象与原型

Reflect.ownKeys 返回的键是什么顺序?和 Object.keys 有什么区别?

Reflect.ownKeys 返回对象自己所有的键,不可枚举的、Symbol 的都在里面;Object.keys 只返回可枚举的字符串键。两者顺序规则一样:整数键从小到大排在最前,然后是字符串键按添加顺序,Symbol 键排在最后。

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

四个 API 的取键范围

  1. Object.keys自身、可枚举、字符串键
  2. Object.getOwnPropertyNames自身、字符串键,不可枚举的也要
  3. Reflect.ownKeys自身所有键,包括不可枚举的和 Symbol 键

像 '1' 这样的整数键总会被排到前面,和你写的顺序无关。用对象存按 ID 排好序的数据时,遍历出来的顺序会被打乱。

核心回答

先记住这个答案

Reflect.ownKeys(obj) 返回对象自身的全部键,包括不可枚举的键和 Symbol 键,等于 Object.getOwnPropertyNames 和 Object.getOwnPropertySymbols 两个结果拼在一起。Object.keys 范围最小,只返回可枚举的字符串键。顺序规则两者一样:先是整数形式的键按数值升序,再是其他字符串键按添加顺序,最后是 Symbol 键按添加顺序。

  • Reflect.ownKeys 包含符号键
  • Object.keys 只要可枚举的字符串键
  • 顺序:整数键升序,字符串按插入,Symbol 最后
  • 都只看自身,不会列出原型上的键

一个对象,两种结果

把整数键、普通字符串键、Symbol 键和不可枚举属性混在一起,差别就很清楚了。

同一个对象分别取键JavaScript
const sym = Symbol('id')
const obj = { b: 1, 2: 'two', a: 2, [sym]: 3, 1: 'one' }
// 加一个不可枚举属性
Object.defineProperty(obj, 'hidden', { value: 4, enumerable: false })

console.log(Object.keys(obj).join(' '))
// Symbol 不能直接拼字符串,先转成字符串
console.log(Reflect.ownKeys(obj).map(String).join(' '))
查看输出与解释
1 2 b a
1 2 b a hidden Symbol(id)

写的时候是 b、2、a、sym、1 的顺序,输出却是 1 和 2 排最前。Object.keys 里没有 hidden 和 Symbol 键;Reflect.ownKeys 全都有,而且 Symbol 键排在所有字符串键后面,哪怕它比 hidden 先定义。

键的顺序是怎么定的

从 ES2015 起,规范规定了普通对象自有键的顺序,ES2020 又把 for...in、Object.keys 这些遍历方法的顺序也统一了。规则分三段。

整数键排最前
能当数组下标的键,比如 '0'、'1'、'42',会按数值从小到大排在最前面。数组能按下标顺序遍历,靠的就是这条。但 '01'、'-1'、'1.5' 不算,它们是普通字符串,按添加顺序排。
字符串键按添加顺序,Symbol 最后
其余字符串键按第一次添加的顺序排列,删掉再重新加,会排到末尾。Symbol 键单独排在所有字符串键之后,内部也按添加顺序。Object.keys、JSON.stringify、Object.entries 都遵守同样的字符串键顺序,只是它们不管 Symbol。

实际代码里什么时候用 Reflect.ownKeys

平时遍历业务数据用 Object.keys 或 Object.entries 就够了,不可枚举属性和 Symbol 通常是内部实现细节,不应该被业务逻辑看到。

需要「一个都不能漏」的场景才用 Reflect.ownKeys。比如手写深拷贝时,想把 Symbol 键也复制过去;比如深度冻结,要把每个属性都处理到;再比如 Proxy 的 ownKeys 陷阱里,一般 return Reflect.ownKeys(target) 作为默认行为,再在此基础上过滤。另外 Reflect.ownKeys 的参数必须是对象,传原始值会抛 TypeError;Object.keys('ab') 却会先把字符串包装成对象,返回 ['0', '1']。

回答前,多想一步

容易答错的地方

以为对象键完全按写的顺序排
整数键永远会被提到前面。用 { 100: ..., 3: ..., 20: ... } 存按热度排好的数据,遍历时会变成 3、20、100。需要保持插入顺序时,用 Map 或者数组。
以为 Object.keys 会返回 Symbol 键
Object.keys、for...in、JSON.stringify 都会跳过 Symbol 键。这也是很多库用 Symbol 做「隐藏」字段的原因,但它不是真正的私有,Reflect.ownKeys 或 Object.getOwnPropertySymbols 都能拿到。
把 Reflect.ownKeys 当成包含原型链的完整列表
名字里的 own 就说明它只看自身。原型上的方法,比如 class 里定义的方法,要对原型对象调用才拿得到。
试着用自己的话回答

面试官还会怎么问?

for...in 和 Object.keys 的结果有什么不同?

for...in 除了自身可枚举的字符串键,还会遍历原型链上可枚举的字符串键。两者都不包括 Symbol 键。对自身键来说,它们的顺序是一致的。

怎么只拿到对象的 Symbol 键?

用 Object.getOwnPropertySymbols(obj)。它返回自身所有 Symbol 键,不区分是否可枚举。

用 Proxy 的 ownKeys 陷阱能随便返回键吗?

不能。返回值必须是字符串和 Symbol 组成的数组,不能有重复;目标对象上不可配置的键必须出现在结果里;目标对象不可扩展时,结果必须和目标的自有键完全一致。违反这些约束,引擎会抛 TypeError。

从一道题,走向一组知识

把知识连起来

对象与原型

Reflect.set 和直接用等号赋值,有什么不一样?

同样是 Reflect 上的方法,Reflect.set 和赋值的区别说明了 Reflect 这组 API 的设计思路。

对象与原型

怎么创建一个可撤销的 Proxy?撤销之后再访问会怎样?

Reflect.ownKeys 对应 Proxy 的 ownKeys 陷阱,撤销后的代理调用它会直接抛 TypeError。

参考资料

  • Reflect.ownKeys()

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

本题目录
  1. 先记住这个答案
  2. 一个对象,两种结果
  3. 键的顺序是怎么定的
  4. 实际代码里什么时候用 Reflect.ownKeys
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

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

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