JavaScript Reflect API: Advanced Architecture
The Reflect object exposes JavaScript's own internal operations as plain functions. Learn every Reflect method, what it returns, and why it exists as its own API.
The Reflect API is a built-in JavaScript object that exposes core language operations, like getting a property, deleting a property, or calling a function, as plain static methods instead of operators or syntax. Calling Reflect.get on an object does the same thing as normal dot notation, but as a function call you can pass around, store, or invoke dynamically.
It exists because operators like delete and in, along with function calls themselves, are built into JavaScript's syntax, which makes them hard to use generically. Reflect gives every one of those operations a matching function with a predictable name and argument list, shown below reading, checking, and removing a property on a plain object:
const user = { name: "Maria", role: "admin" };
console.log(Reflect.get(user, "name"));
console.log(Reflect.has(user, "role"));
console.log(Reflect.deleteProperty(user, "role"));
console.log(user);
// Maria
// true
// true
// { name: 'Maria' }The get method reads a property, has checks whether a property exists the same way the in operator would, and deleteProperty removes it and reports success as true. Each call does what its operator equivalent would do, just written as a function instead of syntax. Reflect is one piece of a larger toolkit; see JavaScript metaprogramming for how it fits alongside Proxy, symbols, and property descriptors.
Reflect Is Not a Constructor
Unlike Array or Map, Reflect cannot be called with new or invoked as a function. It behaves like Math, a plain object that only holds static methods and never gets instantiated on its own.
console.log(typeof Reflect);
// objectCalling Reflect with new throws a TypeError, since Reflect has no constructor behavior defined at all. Every operation happens by calling one of its methods directly, never on an instance you create yourself.
The Full List of Reflect Methods
The table below lists every static method on Reflect, grouped by the kind of operation it performs, along with what each one hands back to the caller.
| Method | What it does | Returns |
|---|---|---|
| get | Reads a property value | The property value |
| set | Assigns a property value | true or false |
| has | Checks if a property exists, including inherited ones | true or false |
| deleteProperty | Deletes a property | true or false |
| ownKeys | Lists every own property key, including symbols and non-enumerable ones | Array of keys |
| apply | Calls a function with a given this and argument list | The function's return value |
| construct | Calls a class or function as if with new | A new instance |
| defineProperty | Defines or redefines a property | true or false |
| getPrototypeOf | Reads the object's prototype | The prototype object or null |
| setPrototypeOf | Changes the object's prototype | true or false |
| getOwnPropertyDescriptor | Reads a property's descriptor | Descriptor object or undefined |
| isExtensible | Checks if new properties can still be added | true or false |
| preventExtensions | Blocks any new properties from being added | true or false |
Most of these read like a direct translation of an existing operator or syntax form into a callable function, which is exactly what makes Reflect useful for code that needs to perform one of these operations dynamically instead of with fixed syntax.
Reflect.get and Reflect.set
The get and set methods are the two you will reach for most often outside of Proxy code, since they replace dot notation and bracket notation with a plain function call:
const config = { theme: "dark", version: 3 };
Reflect.set(config, "version", 4);
console.log(Reflect.get(config, "version"));
// 4The set call returns true here because the assignment succeeded. Both methods accept an optional extra argument called receiver, which controls what this refers to inside a getter or setter. That argument only matters when the target has accessor properties, which is why it appears constantly in Proxy trap code but is rarely needed in plain object work.
Reflect.apply and Reflect.construct
The apply method calls a function with a specific this value and argument array, the same job the older apply method on Function.prototype does, but as a standalone function instead of a method called on the function itself:
function greet(greeting) {
return `${greeting}, ${this.name}`;
}
const user = { name: "Amir" };
console.log(Reflect.apply(greet, user, ["Hello"]));
// Hello, AmirThe construct method does the equivalent job for new. It builds an instance of a class or constructor function without writing that keyword directly in the code, which matters when the class itself is only known dynamically, such as one selected from a lookup object at runtime.
class Product {
constructor(name) {
this.name = name;
}
}
const item = Reflect.construct(Product, ["Keyboard"]);
console.log(item.name);
// KeyboardReflect.ownKeys vs Object.keys
The ownKeys method returns every own property key on an object, including non-enumerable keys and symbol keys, while the older Object.keys method only returns enumerable string keys and leaves out symbols and hidden properties entirely.
const id = Symbol("id");
const record = { name: "Task A", [id]: 101 };
Object.defineProperty(record, "hidden", {
value: true,
enumerable: false,
});
console.log(Object.keys(record));
console.log(Reflect.ownKeys(record));| Call | Result |
|---|---|
| Object.keys(record) | ['name'] |
| Reflect.ownKeys(record) | ['name', 'hidden', Symbol(id)] |
Reach for ownKeys when you need a complete picture of an object's properties, such as writing a generic clone or logging utility. Use the shorter Object.keys for everyday code where only the normal, visible properties matter.
Why Reflect Returns Booleans Instead of Throwing
Operations like assigning to a frozen object silently fail in normal mode and throw in strict mode, which makes their success hard to check consistently across different code. Reflect methods sidestep this entirely by always returning true or false for any operation that can fail:
const frozen = Object.freeze({ id: 1 });
const success = Reflect.set(frozen, "id", 2);
console.log(success);
console.log(frozen.id);
// false
// 1The set call reports false instead of throwing, and frozen.id stays at 1 because the assignment never happened. Calling code can check the result with a normal conditional statement. This predictable boolean return is also why Proxy traps like set and deleteProperty are themselves expected to return a boolean, matching what Reflect already does by default.
When to Use Reflect
Reach for Reflect when writing a Proxy trap that needs the default behavior for an operation, or when an operation like property deletion, function invocation, or key listing needs to happen dynamically rather than through fixed syntax. For combining Reflect directly with Proxy traps, including the receiver argument that fixes a real inheritance bug, see using Reflect and Proxy together in JavaScript. For everyday object work without a Proxy involved, plain dot notation and bracket notation are usually simpler and just as effective.
Rune AI
Key Insights
- Reflect is a built-in object with static methods that mirror JavaScript's internal operations, such as getting, setting, and deleting properties.
- Reflect is not a constructor. You never call it with new.
- Methods like set and deleteProperty return true or false instead of throwing, making success or failure easy to check.
- ownKeys returns every own property key, including non-enumerable ones and symbols, unlike the equivalent Object method.
- Reflect methods share the same name and argument order as Proxy traps, which is why Reflect is the standard tool for forwarding default behavior inside a trap.
Frequently Asked Questions
Is Reflect only useful with Proxy?
Can I call new Reflect()?
Conclusion
Reflect gives you direct, functional access to operations that JavaScript normally performs through operators and syntax, like property access, deletion, and function calls. Its methods return consistent boolean or value results instead of throwing, which makes it the natural companion for Proxy traps and any code that needs to perform these operations dynamically.
More in this topic
Using Reflect and Proxy Together in JavaScript
Proxy traps intercept operations, but Reflect is what makes them behave correctly. Learn why Reflect belongs inside every trap and what breaks when you skip it.
Top JS Array Methods Interview Questions to Know
The array method questions that come up most often in JavaScript interviews, answered directly with short examples: map vs forEach, mutating vs non-mutating methods, reduce, and more.
JS Metaprogramming: Advanced Architecture Guide
Metaprogramming means writing code that inspects or changes how other code behaves. See how Proxy, Reflect, Symbol, and property descriptors work together as JavaScript's metaprogramming toolkit.