Object.getOwnPropertyNames()
Object.keys with the filter removed. It is an introspection tool rather than an iteration tool — the properties it reveals are usually hidden for a reason.
Demo
The array cases are the demonstrable difference. Object.keys([10,20]) gives just the indices; this gives '0', '1' and 'length' — because length is a genuine own property of every array, merely a non-enumerable one. An empty array still has it, which is why the second case returns a one-element list rather than nothing. On a plain object parsed from JSON the two methods agree, since everything created by assignment or a literal is enumerable. What this demo cannot show is a property hidden with defineProperty, because JSON has no way to express one.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| object | object | yes | The object to inspect. Primitives are coerced; null and undefined throw TypeError. |
Return value
string[] — Every own STRING key, enumerable or not. Symbol keys are excluded — those need getOwnPropertySymbols.
Common patterns
Object.getOwnPropertyNames(Object.getPrototypeOf(instance));
const all = [ ...Object.getOwnPropertyNames(o), ...Object.getOwnPropertySymbols(o), ];
for (const k of Object.keys(o)) { }
Examples
Pitfalls
class A { m() {} } Object.getOwnPropertyNames(new A())
Object.getOwnPropertyNames(A.prototype)
Object.getOwnPropertyNames({[Symbol("s")]: 1})
Object.getOwnPropertySymbols({[Symbol("s")]: 1}).length
Object.getOwnPropertyNames([1, 2]).map(k => k)
Object.keys([1, 2])
class C { #s = 1; } Object.getOwnPropertyNames(new C())
class C { #s = 1; get s() { return this.#s; } }
When to use
- Introspection, debugging and tooling
- Listing the methods on a prototype
- Copying an object including non-enumerable properties
- Understanding why a property is missing from Object.keys
- Iterating data → Object.keys
- You need symbol keys → getOwnPropertySymbols as well
- You need inherited properties → walk the prototype chain
- You want values or pairs → Object.values or Object.entries
Notes
FAQ
Because length is a real own property that happens to be non-enumerable. Object.keys filters on the enumerable flag; this method does not. The same applies to most built-in properties, which are non-enumerable so they stay out of for...in loops.
Object.getOwnPropertyDescriptor([1], "length"); // {value: 1, writable: true, enumerable: false, configurable: false}