How does Reflect differ from Object?
Reflect and Object really are similar (both work with object properties), but they are built for different purposes. The difference between them is in philosophy, behavior, and use.
Let's break it down step by step:
Short answer
| Criterion | Object | Reflect |
|---|---|---|
| Main purpose | Working with objects (creation, prototypes, properties) | Metaprogramming - "controlling the behavior" of objects |
| Appeared | Since the start of JS | In ES6 (ES2015) |
| Behavior on error | Throws exceptions | Returns true / false |
| Used in | regular code | Proxy, safe calls, internal operations |
| Return type | Varies (object, value, etc.) | Almost always boolean or a primitive |
| Status | "old" API | "modern, reflective" API |
Example - defineProperty
Object:
try {
Object.defineProperty({}, 'x', { value: 1, writable: false });
console.log('ok');
} catch {
console.log('Error!');
}If the operation fails (for example, the object is frozen), it throws an error.
Reflect:
const obj = Object.freeze({});
const result = Reflect.defineProperty(obj, 'x', { value: 1 });
console.log(result); // false (no error)Reflect.defineProperty() simply returns false instead of interrupting the program.
Example - removing a property
Via delete
const user = { name: 'Tim' };
delete user.name; // trueVia Reflect (safer)
const user = { name: 'Tim' };
console.log(Reflect.deleteProperty(user, 'name')); // true
console.log(Reflect.deleteProperty(Object.freeze({x: 4}), 'x')); // falseReflect.deleteProperty() does the same thing, but does not throw errors and returns a boolean result.
Example - calling a function
function greet(msg) {
console.log(msg, this.name);
}
const user = { name: 'Tim' };
Reflect.apply(greet, user, ['Hi']); // "Hi Tim"Reflect.apply() is an analog of Function.prototype.apply(), but more explicit and convenient for Proxy traps and metaprogramming.
Example - creating an object
class User {
constructor(name) {
this.name = name;
}
}
const tim = Reflect.construct(User, ['Tim']);
console.log(tim.name); // "Tim"Reflect.construct() is a "reflective" version of new, useful when you need to dynamically create a class instance.
Example - checking a property
const user = { name: 'Tim' };
console.log('name' in user); // true
console.log(Reflect.has(user, 'name')); // trueReflect.has() is the same as the in operator, but as a function (convenient for dynamic calls).
Example - getting and setting a property
const user = { name: 'Tim' };
Reflect.set(user, 'name', 'Oleh');
console.log(Reflect.get(user, 'name')); // "Oleh"An analog of user.name = ... and user.name, but in a "functional" form (convenient to use in Proxy).
Error behavior
| Method | Object | Reflect |
|---|---|---|
Object.defineProperty(frozen, 'x', {...}) | throws an error | returns false |
Object.getPrototypeOf(null) | TypeError | returns false |
Object.setPrototypeOf(sealed, ...) | throws an error | returns false |
So Reflect is a "quiet" and predictable variant of Object methods.
Methods that Object does not have
| Reflect method | What it does | Analog |
|---|---|---|
Reflect.apply() | Calls a function with the given this and arguments | func.apply() |
Reflect.construct() | Analog of the new operator | - |
Reflect.get() / Reflect.set() | Gets / sets a property value | obj[key] |
Reflect.has() | Checks for a property | 'key' in obj |
Reflect.deleteProperty() | Deletes a property | delete obj.key |
Reflect.ownKeys() | Returns all keys (including Symbol) | Object.getOwnPropertyNames() + Object.getOwnPropertySymbols() |
Real-world example - Proxy
Reflect works perfectly together with Proxy to pass through the default standard behavior.
const user = { name: 'Tim' };
const proxy = new Proxy(user, {
get(target, key) {
console.log(`Reading ${key}`);
return Reflect.get(target, key); // safely delegate
}
});
console.log(proxy.name);
// Output:
// Reading name
// "Tim"Without Reflect.get() you would have to manually write target[key], which can cause errors in more complex cases (accessors, prototypes, etc.).
Summary
| Criterion | Object | Reflect |
|---|---|---|
| Purpose | Working with properties and prototypes | Metaprogramming, "reflecting" behavior |
| Appeared | Since the start of JS | ES6 (2015) |
| On error | Throws an exception | Returns false |
| Return value | Varies | Predictable |
| Proxy support | No | Yes |
| Convenience in functional calls | Medium | High |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.