如何在JavaScript中按声明顺序获取含Symbol的对象键名?
按插入/声明顺序获取包含Symbol的所有对象自有键
原生JavaScript没有内置API能直接实现你想要的效果——即不区分键类型(字符串/Symbol),完全按属性的声明/插入顺序返回所有自有键。这是因为ECMAScript规范对Reflect.ownKeys()的返回顺序做了硬性规定:
- 优先返回所有整数类型的键(按数值升序排列)
- 其次返回所有非整数的字符串键(按插入顺序排列)
- 最后返回所有Symbol类型的键(按插入顺序排列)
这种分组规则导致字符串键和Symbol键始终被分开返回,无法直接得到混合顺序的结果。
可行的实现方案
1. 用Proxy自动跟踪属性顺序(适用于可控制对象创建的场景)
如果你能掌控对象的创建过程,可以通过Proxy拦截属性的添加/删除操作,自动维护一个记录顺序的数组。这种方式无需手动维护键名数组,Proxy会自动跟踪:
function createOrderedObject() { const keyOrder = []; const target = {}; const proxy = new Proxy(target, { set(obj, prop, value) { // 仅当属性不存在时记录顺序 if (!Reflect.has(obj, prop)) { keyOrder.push(prop); } return Reflect.set(obj, prop, value); }, deleteProperty(obj, prop) { // 删除属性时同步移除顺序记录 const index = keyOrder.indexOf(prop); if (index !== -1) { keyOrder.splice(index, 1); } return Reflect.deleteProperty(obj, prop); } }); // 添加获取顺序键的方法 proxy.getOrderedOwnKeys = () => [...keyOrder]; return proxy; } // 使用示例 const symbolProp = Symbol('symbolProperty'); const obj = createOrderedObject(); obj[symbolProp] = 'Symbol Property'; obj.regularProperty = 'Regular Property'; console.log(obj.getOrderedOwnKeys()); // 输出: [Symbol(symbolProperty), "regularProperty"]
2. 编译阶段处理(仅适用于对象字面量)
如果你的场景只涉及对象字面量,可以通过Babel插件等工具在编译阶段提取属性的声明顺序,生成包含顺序信息的代码。但这种方式属于构建时处理,无法作用于运行时动态创建的任意对象,局限性较强。
补充说明
你提到Object.getOwnPropertyNames()的行为依赖实现,这是ES2015之前的历史问题。在ES2015及之后的规范中,非整数类型的字符串键的返回顺序已被明确为插入顺序,现代浏览器和Node.js环境中该方法的返回顺序是稳定可预测的。
内容的提问来源于stack exchange,提问作者Ood
相关产品推荐
相关产品推荐

