Object.getOwnPropertyDescriptor()
The inspection half of the descriptor system. Its plural form is the missing piece for copying an object faithfully, because Object.assign flattens getters into values.
Demo
A property created by a literal or by JSON parsing comes back with all three flags true — writable, enumerable, configurable — which is what plain assignment always produces. The third case shows that inherited properties give undefined: toString exists on the prototype, not on this object, so there is no OWN descriptor to report. The last case is worth looking at: an array length is writable but NOT enumerable and NOT configurable, which is exactly why it never appears in Object.keys and cannot be deleted.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| object | object | yes | The object to inspect. Primitives are coerced; null and undefined throw. |
| key | string | symbol | yes | The property key. Only own properties are considered — the prototype chain is not searched. |
Return value
object | undefined — A descriptor object — value and writable for a data property, get and set for an accessor, plus enumerable and configurable. undefined if the property is not an OWN property.
Common patterns
Object.create( Object.getPrototypeOf(src), Object.getOwnPropertyDescriptors(src) );
const d = Object.getOwnPropertyDescriptor(o, k); if (d?.writable) o[k] = v;
const isAccessor = "get" in (Object.getOwnPropertyDescriptor(o, k) ?? {});
Examples
Pitfalls
Object.getOwnPropertyDescriptor({}, "toString")
"toString" in {}
const s = {get now() { return Date.now(); }}; Object.assign({}, s).now
Object.defineProperties({}, Object.getOwnPropertyDescriptors(s))
const d = Object.getOwnPropertyDescriptor(o, "a"); d.value = 99; o.a
Object.defineProperty(o, "a", d)
Object.getOwnPropertyNames({[Symbol("s")]: 1})
Object.getOwnPropertySymbols({[Symbol("s")]: 1}).length
When to use
- Copying an object with getters, setters and flags preserved
- Inspecting why a property is invisible or read-only
- Writing generic code that must respect property attributes
- Debugging an object that does not behave as its literal suggests
- You only want the value → read the property
- You only want to know it exists → Object.hasOwn or in
- A shallow merge is enough → Object.assign or spread
- You want to list keys → Object.keys or getOwnPropertyNames
Notes
FAQ
Combine the prototype with every descriptor. This preserves getters, setters, non-enumerable properties and symbol keys — all of which Object.assign and spread silently discard or flatten.
const copy = Object.create( Object.getPrototypeOf(src), Object.getOwnPropertyDescriptors(src) );