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.

8 min read

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:

javascriptjavascript
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.

javascriptjavascript
console.log(typeof Reflect);
// object

Calling 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.

MethodWhat it doesReturns
getReads a property valueThe property value
setAssigns a property valuetrue or false
hasChecks if a property exists, including inherited onestrue or false
deletePropertyDeletes a propertytrue or false
ownKeysLists every own property key, including symbols and non-enumerable onesArray of keys
applyCalls a function with a given this and argument listThe function's return value
constructCalls a class or function as if with newA new instance
definePropertyDefines or redefines a propertytrue or false
getPrototypeOfReads the object's prototypeThe prototype object or null
setPrototypeOfChanges the object's prototypetrue or false
getOwnPropertyDescriptorReads a property's descriptorDescriptor object or undefined
isExtensibleChecks if new properties can still be addedtrue or false
preventExtensionsBlocks any new properties from being addedtrue 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:

javascriptjavascript
const config = { theme: "dark", version: 3 };
 
Reflect.set(config, "version", 4);
console.log(Reflect.get(config, "version"));
// 4

The 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:

javascriptjavascript
function greet(greeting) {
  return `${greeting}, ${this.name}`;
}
 
const user = { name: "Amir" };
console.log(Reflect.apply(greet, user, ["Hello"]));
// Hello, Amir

The 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.

javascriptjavascript
class Product {
  constructor(name) {
    this.name = name;
  }
}
 
const item = Reflect.construct(Product, ["Keyboard"]);
console.log(item.name);
// Keyboard

Reflect.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.

javascriptjavascript
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));
CallResult
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:

javascriptjavascript
const frozen = Object.freeze({ id: 1 });
 
const success = Reflect.set(frozen, "id", 2);
console.log(success);
console.log(frozen.id);
// false
// 1

The 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

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.
RunePowered by Rune AI

Frequently Asked Questions

Is Reflect only useful with Proxy?

No. Reflect methods work on any object, with or without a Proxy involved. Using Proxy is the most common reason to reach for Reflect, since traps and Reflect methods share the same names and arguments, but a method like has or ownKeys is useful anywhere you would otherwise use the in operator or a plain Object method.

Can I call new Reflect()?

No. Reflect is not a constructor and cannot be called with new or invoked as a function. It is a plain object that holds static methods, similar to Math.

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.