reflect.ownkeys 返回键数组严格按插入顺序排列:先数值字符串键升序,再其余字符串键添加顺序,最后 symbol 键创建顺序;支持原生遍历与链式操作,且覆盖所有自身属性类型。

Reflect.ownKeys 返回的键数组有明确、可预测的顺序,不是随机的,也不是按字典序排列——它严格遵循 JavaScript 规范定义的**插入顺序规则**,这对可靠遍历和调试至关重要。
排序规则:三段式固定顺序
返回的键数组按以下优先级分组排列:
- 所有整数索引字符串键(如 "0"、"1"、"100"),按数值升序排列
- 其余字符串键(含空格、emoji、中文、非法标识符等),按属性被添加到对象时的顺序排列
- 所有Symbol 键,按它们被创建并赋值到对象上的顺序排列
例如:Reflect.ownKeys({ [Symbol('z')]: 1, 'b': 2, 2: 3, 'a': 4, 1: 5, [Symbol('a')]: 6 }) 结果为:["1", "2", "b", "a", Symbol(a), Symbol(z)] —— 先排数字键(1→2),再排非数字字符串键(b 先于 a,因 b 更早添加),最后是 Symbol(a 先于 z)。
遍历特性:原生数组 + 零中间转换
返回值是标准数组,天然支持现代遍历方式,无需额外封装或类型转换:
-
for (const key of Reflect.ownKeys(obj)) { ... }—— 最轻量,无拷贝,适合纯遍历 -
Reflect.ownKeys(obj).map(key => [key, obj[key]])—— 一键提取全部键值对,含 Symbol -
Reflect.ownKeys(obj).filter(k => typeof k === 'symbol')—— 快速分离 Symbol 键 - 配合
Array.from()或展开运算符也完全兼容,如[...Reflect.ownKeys(obj)]
不排序 ≠ 无序:别误用 .sort()
它本身不自动排序,但顺序稳定且可复现。若强行调用 .sort():
- 字符串键可正常比较排序
- Symbol 键无法直接比较,
Symbol() 恒为 <code>false,会打乱原有插入顺序,甚至引发NaN或意外行为 - 混合类型数组(string | symbol)调用
.sort()会导致类型混排,语义丢失
如需统一排序逻辑,应先分离类型,再分别处理。
与 for...in / Object.keys 的关键差异
这些方法都不满足“全量+有序”要求:
-
for...in:遍历原型链,跳过不可枚举属性,完全忽略 Symbol -
Object.keys():只返回可枚举字符串键,漏掉不可枚举项和所有 Symbol -
Object.getOwnPropertyNames():覆盖不可枚举字符串键,但仍不包含 Symbol
只有 Reflect.ownKeys() 同时满足:自身属性、全类型覆盖、顺序确定、无原型污染。











