Reflect.ownKeys 是最完整、最符合规范的键名枚举方式,能获取对象自身所有字符串和 Symbol 键,严格排除原型链属性,按规范定义顺序返回,且为原子操作。

Reflect.ownKeys 能获取对象自身所有类型的键名(包括字符串、Symbol),且保持与 for...in、Object.keys 等方法不同的遍历顺序和覆盖范围,是目前最完整、最符合语言规范的键名枚举方式。
覆盖所有键类型,不遗漏 Symbol
Object.keys 和 Object.getOwnPropertyNames 都只返回字符串键,会忽略 Symbol 类型的自有属性。而 Reflect.ownKeys 同时返回字符串和 Symbol 键:
const obj = {
a: 1,
[Symbol('b')]: 2
};
Object.keys(obj); // ['a']
Object.getOwnPropertyNames(obj); // ['a']
Reflect.ownKeys(obj); // ['a', Symbol(b)]
严格返回“自有”属性,不污染原型链
for...in 会遍历原型链上的可枚举属性,Object.keys 虽然只查自有属性,但无法识别不可枚举字符串键(如通过 Object.defineProperty 添加的 enumerable: false 属性)。Reflect.ownKeys 则完整包含所有自有属性键,无论是否可枚举、是否为字符串或 Symbol:
const parent = { x: 1 };
const child = Object.create(parent);
Object.defineProperty(child, 'y', {
value: 2,
enumerable: false
});
child[Symbol('z')] = 3;
Reflect.ownKeys(child); // ['y', Symbol(z)]
// 注意:x 不出现(非自有),y 出现(自有但不可枚举),Symbol(z) 也出现
保证标准定义的枚举顺序
ECMAScript 规范明确定义了 Reflect.ownKeys 的返回顺序:先按创建顺序排列整数索引(如 '0', '1'),再按添加顺序排列其余字符串键,最后按添加顺序排列 Symbol 键。这种可预测的顺序对序列化、深比较、代理拦截等场景至关重要:
用于 inference.sh 的 JavaScript/TypeScript SDK,可运行 AI 应用、构建代理、集成 150+ 模型。包名:@inferencesh/sdk(npm install),完整 TypeScript 支持。
立即学习“Java免费学习笔记(深入)”;
- 比 for...in 或 Object.keys 更可靠,不受属性定义顺序以外的因素干扰
- 在 Proxy 中常用于 trap(如 ownKeys)的返回值,必须遵守该顺序才符合规范
- 适合构建确定性哈希、结构化克隆逻辑等需要稳定键序的工具函数
与 Object.getOwnPropertyNames + Object.getOwnPropertySymbols 组合效果一致,但更简洁安全
过去常用两者拼接来模拟全部键:
[...Object.getOwnPropertyNames(obj), ...Object.getOwnPropertySymbols(obj)]
但这存在两个隐患:一是两次调用可能因对象被修改导致结果不一致;二是若对象有自定义 @@iterator 或拦截 getOwnPropertyNames,行为可能异常。Reflect.ownKeys 是原子操作,由引擎统一实现,语义清晰、性能更好、兼容性稳定(ES6+ 全平台支持)。

















