Reflect.ownKeys() 返回对象所有自身键名(含不可枚举字符串键和所有Symbol键),按数字索引字符串键升序、其他字符串键创建顺序、Symbol键创建顺序排列,覆盖Object.keys()、getOwnPropertyNames()与getOwnPropertySymbols()的全部范围。

Reflect.ownKeys() 是 ES6 提供的静态方法,用于获取对象**自身所有键名**(包括字符串键和 Symbol 键),且**不区分可枚举性**——也就是说,它会返回所有自有属性的键,无论是否可枚举、是否是 Symbol 类型。
它能拿到哪些键?
Reflect.ownKeys(obj) 返回一个数组,包含对象自身的:
- 所有字符串键(包括不可枚举的,比如通过
Object.defineProperty设置的enumerable: false属性) - 所有 Symbol 键(无论是否可枚举)
它不会包含继承来的属性,也不会过滤掉不可枚举属性——这点和 Object.keys()(只返回可枚举字符串键)、Object.getOwnPropertyNames()(返回所有自有字符串键,不含 Symbol)、Object.getOwnPropertySymbols()(只返回自有 Symbol 键)都不同。
和 Object API 的对比
假设你有这样一个对象:
const obj = {};
obj.a = 1;
Object.defineProperty(obj, 'b', { value: 2, enumerable: false });
obj[Symbol('c')] = 3;
obj[Symbol.for('d')] = 4;
那么:
-
Object.keys(obj)→['a'](仅可枚举字符串键) -
Object.getOwnPropertyNames(obj)→['a', 'b'](所有自有字符串键) -
Object.getOwnPropertySymbols(obj)→[Symbol(c), Symbol(d)](所有自有 Symbol 键) -
Reflect.ownKeys(obj)→['a', 'b', Symbol(c), Symbol(d)](全部自有键,按创建顺序:字符串先升序,Symbol 按创建顺序)
注意键的排序规则
Reflect.ownKeys 的返回结果遵循固定顺序:
- 先按字符串键的“数字索引”升序排列(如 '0', '1', '10' → 实际是 '0', '1', '10',不是字典序)
- 再按其他字符串键的创建顺序(即
for...in中的顺序,但不含继承属性) - 最后是 Symbol 键,按它们被创建的顺序
这个顺序与 Object.getOwnPropertyNames() + Object.getOwnPropertySymbols() 拼接后的顺序一致,但 Reflect.ownKeys 是原子操作,更可靠。
实际使用建议
当你需要完整遍历一个对象的自有结构(比如做深克隆、序列化、代理拦截、调试检查),推荐优先用 Reflect.ownKeys():
- 避免漏掉不可枚举属性(如 Node.js 中某些内置对象的隐藏字段)
- 自动兼容 Symbol 键,无需额外调用
getOwnPropertySymbols - 语义清晰:“我要所有自己的键”,一行代码搞定
例如:
function shallowCopy(obj) {
const keys = Reflect.ownKeys(obj);
const copy = {};
for (const key of keys) {
copy[key] = obj[key];
}
return copy;
}
这样复制能保留不可枚举属性和 Symbol 属性(值本身会被拷贝,但属性描述符如 writable 不会)。


















