在排查对象结构、处理框架内部标记属性,或者想确认“这个属性到底存不存在”时,很多人会发现 Object.keys() 看得并不完整。要把对象自身的字符串属性名一次性找全,尤其把不可枚举属性也列出来,关键就是用 Object.getOwnPropertyNames();看完本文,你可以快速判断它适合什么场景、和哪些 API 搭配使用。
Object.getOwnPropertyNames() 到底返回什么
Object.getOwnPropertyNames() 用于获取对象自身所有属性名,返回值是一个字符串数组。这里的“所有”包括两类:
- 对象直接定义的自有属性
- 设置了
enumerable: false的不可枚举属性
它不会返回两类内容:
- 原型链上的继承属性
Symbol类型属性
也就是说,如果一个对象有 a(可枚举)、b(不可枚举)、c(可枚举),那么结果会是 ['a', 'b', 'c']。
它和 Object.keys() 有什么区别
这两个 API 最容易混淆的点,在于是否包含不可枚举属性。

Object.keys() 只返回可枚举的自有属性名;Object.getOwnPropertyNames() 则会把不可枚举属性也一并返回,因此更适合做完整检查。
const obj = { a: 1 };
Object.defineProperty(obj, 'b', {
value: 2,
enumerable: false // 不可枚举
});
Object.defineProperty(obj, 'c', {
value: 3,
enumerable: true// 可枚举
});
console.log(Object.keys(obj)); // ['a', 'c']
console.log(Object.getOwnPropertyNames(obj)); // ['a', 'b', 'c']
从这段代码可以直接看出:
a和c都是可枚举属性,所以会出现在Object.keys(obj)的结果里b虽然存在于对象本身,但由于不可枚举,不会被Object.keys()返回Object.getOwnPropertyNames(obj)会把b也列出来,因此结果更完整
如果你的目标只是遍历常规业务字段,Object.keys() 往往已经够用;但如果你在调试、做底层处理或检查对象真实结构,Object.getOwnPropertyNames() 更合适。
哪些场景更适合用它
调试对象时看清“隐藏属性”
有些属性明明已经挂在对象上,却因为不可枚举,在常规遍历或日志里不容易被注意到。这时用 Object.getOwnPropertyNames(),可以先确认对象到底有哪些自有属性。

深拷贝或序列化前做完整检查
如果对象里带有某些库内部使用的标记属性,而这些属性被定义为不可枚举,那么只依赖 Object.keys() 可能会遗漏它们。先取出完整属性名,再决定哪些需要保留、过滤或复制,会更稳妥。
配合属性描述符进一步判断
Object.getOwnPropertyNames() 只负责把属性名列出来;如果你还要确认属性是否可写、是否可配置,通常会继续配合 Object.getOwnPropertyDescriptor() 使用。这样既能知道“有没有这个属性”,也能知道“这个属性是怎么定义的”。
使用时要注意的边界
- 它不会遍历原型链。如果你还想拿到继承属性,需要继续结合
Object.getPrototypeOf()向上查找。 - 它返回的是属性名,不是属性值。拿到名字后,通常还要配合
obj[prop]或Object.getOwnPropertyDescriptor()继续读取内容。 Symbol属性不会出现在结果中;这部分需要用Object.getOwnPropertySymbols()单独获取。
因此,Object.getOwnPropertyNames() 更准确的定位是:获取对象自身全部字符串键的完整清单,而不是对象全部属性形式的唯一入口。
实际开发里怎么选
如果你只关心可枚举的业务字段,直接用 Object.keys() 即可,结果更贴近日常遍历行为。若你需要确认对象本身的完整字符串属性集合,尤其是排查不可枚举属性、做底层复制或分析对象结构时,优先考虑 Object.getOwnPropertyNames()。
一句话概括:想看“正常会被遍历出来的字段”,用 Object.keys();想看“对象自己到底定义了哪些字符串属性”,用 Object.getOwnPropertyNames()。









