Skip to main content

Reflect.defineProperty()

Reflect.defineProperty() defines (adds or changes) an object property with a given descriptor and returns a boolean value telling you whether it succeeded. It is the modern counterpart of Object.defineProperty(), but with more predictable and safer behaviour: here a failure is an ordinary result rather than an exception.

Theory

TL;DR

  • Syntax: Reflect.defineProperty(target, propertyKey, descriptor).
  • Returns true on success and false on failure, not the object itself.
  • It does not throw on failure, so no try/catch is needed.
  • It accepts both a data descriptor (value, writable) and an accessor descriptor (get, set).
  • Keys can be a string or a Symbol.
  • Main uses: safe checks, metaprogramming and Proxy traps.

Quick example

javascript
const user = {}; const result = Reflect.defineProperty(user, 'name', { value: 'Maria', writable: true, enumerable: true, configurable: true }); console.log(result); // true console.log(user.name); // "Maria"

This is the same as Object.defineProperty(user, 'name', { ... }), with one important difference: Reflect does not throw an error, it simply returns false.

Signature and arguments

javascript
Reflect.defineProperty(target, propertyKey, descriptor)
ArgumentDescription
targetThe object on which the property is defined
propertyKeyThe property name (a string or a Symbol)
descriptorThe descriptor, an object with flags (value, writable, enumerable, configurable, get, set)

What it returns:

  • true if the property was defined successfully;
  • false if the operation failed (for example, the object is protected by Object.freeze() or the property is non-configurable).

Difference from Object.defineProperty()

BehaviourObject.defineProperty()Reflect.defineProperty()
Returnsthe object itselftrue / false
On failurethrows an exceptionreturns false
Suited toordinary codesafe, "reflective" operations

"Reflective" means working with the internal properties of objects without throwing errors.

A safe check in practice:

javascript
const frozen = Object.freeze({}); try { Object.defineProperty(frozen, 'x', { value: 1 }); } catch (e) { console.log('Error:', e.message); } console.log(Reflect.defineProperty(frozen, 'x', { value: 1 })); // false, no exception

Reflect.defineProperty() simply returns false instead of throwing.

Descriptors: data and accessor

The method works identically for data and accessor descriptors:

javascript
const person = {}; Reflect.defineProperty(person, 'fullName', { get() { return 'Maria Koval'; }, enumerable: true }); console.log(person.fullName); // "Maria Koval"

Here the property is described by a getter rather than a value, and Reflect.defineProperty() accepts such a descriptor without any caveats.

Defining properties dynamically and conditionally

The method is convenient inside a loop, when the set of keys is only known at run time:

javascript
const obj = {}; ['name', 'age', 'city'].forEach(key => { Reflect.defineProperty(obj, key, { value: key.toUpperCase(), enumerable: true }); }); console.log(obj); // { name: 'NAME', age: 'AGE', city: 'CITY' }

The return value is useful directly inside a condition:

javascript
if (Reflect.defineProperty(user, 'role', { value: 'admin' })) { console.log('Property added successfully'); } else { console.log('Failed to add property'); }

This is handy precisely because it requires no try/catch: the result is checked like any other boolean expression.

Working with Proxy

Inside a Proxy defineProperty trap, Reflect.defineProperty is used to delegate the default behaviour:

javascript
const target = {}; const proxy = new Proxy(target, { defineProperty(target, key, descriptor) { console.log(`Defining property "${String(key)}"`); return Reflect.defineProperty(target, key, descriptor); } }); proxy.x = 10; // under the hood this calls Reflect.defineProperty automatically

In a Proxy, the reflective methods (Reflect.*) make it easy to implement behaviour as naturally as possible: the trap signature matches the signature of the matching Reflect method, and the boolean result is exactly what the trap is supposed to return.

Summary table:

QuestionAnswer
What it doesDefines (creates or changes) an object property with the given descriptor
What it returnstrue on success, false on failure
Does it throwNo
Does it use a descriptorYes (value, writable, configurable, enumerable, get, set)
Where it is usedSafe operations, Proxy, metaprogramming

Common mistakes

  • Expecting the method to return an object. Object.defineProperty() returns the object and therefore chains, while Reflect.defineProperty() returns true / false. Writing Reflect.defineProperty(obj, 'a', d).b will break.
  • Ignoring the return value. Since there is no exception, a silent failure goes unnoticed. If the result matters, check it.
  • Wrapping the call in try/catch "just in case". For a failed property definition that is pointless: the whole point of Reflect is to avoid the exception. An exception is only possible for invalid arguments, for example when target is not an object.
  • Forgetting that the flags default to false. The descriptor { value: 1 } creates a property that is not writable, enumerable or configurable, so it will not show up in Object.keys() and will not change on assignment.
  • Confusing it with Reflect.getOwnPropertyDescriptor(). The first sets a descriptor, the second reads one.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.