Skip to main content

The Reflect object

Reflect is a built-in object that holds a set of helper methods for working with objects: accessing properties, deleting them, defining them, calling functions and so on. In plain terms, Reflect is a set of "safe" counterparts to JavaScript operators (in, delete, [], Object.defineProperty() and friends) collected in one place.

Theory

TL;DR

  • Reflect is a built-in object, not a function and not a constructor: new Reflect() is impossible.
  • It gives a single interface to low-level operations on objects.
  • Its methods return true or false instead of throwing when an operation is impossible.
  • Every Proxy trap has a matching Reflect method with the same name and the same signature.
  • Inside traps, Reflect guarantees that this is passed correctly through the receiver argument.

Quick example

javascript
const user = { name: 'Tim' }; console.log(Reflect.get(user, 'name')); // 'Tim' Reflect.set(user, 'age', 25); console.log(user); // { name: 'Tim', age: 25 } console.log(Reflect.has(user, 'age')); // true Reflect.deleteProperty(user, 'age'); console.log(Reflect.has(user, 'age')); // false

The main goals of Reflect

  1. A single interface for low-level operations on objects, instead of a scattering of operators and functions (delete, in, Object.defineProperty and so on).
  2. Working together with Proxy, so that you can delegate actions back to the original object.
  3. More predictable behaviour: methods return true or false without throwing when the operation is impossible.
MethodWhat it doesEquivalent without Reflect
Reflect.get(obj, prop)Returns the value of a propertyobj[prop]
Reflect.set(obj, prop, value)Sets the value of a propertyobj[prop] = value
Reflect.has(obj, prop)Checks whether a property exists'prop' in obj
Reflect.deleteProperty(obj, prop)Deletes a propertydelete obj[prop]
Reflect.ownKeys(obj)Returns all keys, including Symbol onesObject.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj))
Reflect.defineProperty(obj, prop, desc)Defines a propertyObject.defineProperty(obj, prop, desc)
Reflect.getOwnPropertyDescriptor(obj, prop)Gets a property descriptorObject.getOwnPropertyDescriptor(obj, prop)
Reflect.apply(fn, thisArg, argsArray)Calls a function with a context and argumentsfn.apply(thisArg, argsArray)
Reflect.construct(fn, argsArray)Creates an instance, like new fn(...)new fn(...argsArray)

Reflect and Proxy together

Reflect is often used inside Proxy traps, to forward the default behaviour back to the target object (target).

javascript
const user = { name: 'Tim' }; const proxy = new Proxy(user, { get(target, prop, receiver) { console.log(`Reading property: ${prop}`); // safer than target[prop]: return Reflect.get(target, prop, receiver); }, set(target, prop, value, receiver) { console.log(`Writing property: ${prop} = ${value}`); return Reflect.set(target, prop, value, receiver); } }); proxy.name; // log: Reading property: name proxy.age = 30; // log: Writing property: age = 30

Why do it this way? Because Reflect guarantees that this and the internal context are passed correctly, unlike direct access through target[prop]. On top of that, Reflect.set returns a ready true or false, which is exactly what the set trap is required to return.

Summary

ItemDescription
ReflectA built-in object with methods for working with objects
GoalUnify low-level operations (read, write, delete, define and so on)
Distinctive traitSafe counterparts to operators, returning true or false instead of errors
Used most oftenInside Proxy traps

Common mistakes

  • Calling Reflect as a function or a constructor. It is a plain namespace object; new Reflect() throws a TypeError.
  • Confusing Reflect.defineProperty with Object.defineProperty. The first returns false, the second throws a TypeError, which is exactly why Reflect is the better fit inside traps.
  • Forgetting to pass receiver to Reflect.get and Reflect.set. Without it, getters and setters inherited from a prototype receive the wrong this.
  • Assuming Reflect.ownKeys returns only string keys. It returns symbols and non-enumerable properties too, unlike Object.keys.
  • Using target[prop] inside a get trap. It breaks inheritance and makes the proxy opaque for classes with getters.
  • Thinking Reflect replaces Object. Some Object methods (Object.keys, Object.assign and others) have no Reflect counterpart; the two sets serve different purposes.

Short Answer

Interview ready
Premium

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