Mastering JavaScript Proxy and Reflect API (Without the Headache)
Table of Contents
What’s the Deal with JavaScript Proxy?
- Real-life Example: Tracking Object Changes (The Simple Way)
When You’d Want to Use a Proxy
Building Reactive Objects (Yeah, Vue Does This)
Lazy Objects: Only Create What You Need
How Proxy and Reflect are the Perfect Duo
- Real-life Example: Logging with Style
Introduction 👋
Let’s talk about two of probably the most underrated (and underused) features of JavaScript: Proxy and Reflect. I get it — you’ve probably heard of them, maybe even Googled them once or twice, but they seem a little extra, right?
But here’s the thing: these tools can unlock a whole new level of control over your objects, and they’re not as hard to use as you might think. By the end of this post, you’ll know exactly how they work, why they’re awesome, and how to add them to your toolbox for practical, real-world scenarios.
Let’s dive in!
What’s the Deal with JavaScript Proxy?
A Proxy in JavaScript is like the ultimate middleman. It lets you intercept and customize how you interact with objects. You can control what happens when someone tries to access, modify, or delete a property. And the best part? It’s super easy to use.
Think of it this way: you’ve got an object — say, a user profile — and you want to make sure anyone messing with that object doesn’t do anything weird (like setting their age to “gibberish”). With a Proxy, you can jump in and take control.
Here’s the basic syntax:
let proxy = new Proxy(target, handler);
target: The original object (the one we’re wrapping).
handler: An object with functions (called traps) that intercept operations like reading, writing, or deleting properties.
Real-life Example: Tracking Object Changes (The Simple Way)
Let’s say you’re building a collaborative editing app, and you want to know every time someone updates the document. Easy enough with a Proxy:
const documentModel = { title: "Draft", content: "Hello World" };
const handler = {
set(target, prop, value) {
console.log(`Property ${prop} is changing from ${target[prop]} to ${value}`);
target[prop] = value;
return true;
}
};
const documentProxy = new Proxy(documentModel, handler);
documentProxy.title = "Final Draft"; // Logs: Property title is changing from Draft to Final Draft
Every time the document changes, you get a nice little log showing exactly what happened. No surprises here.
When You’d Want to Use a Proxy
So, when should you actually use a Proxy? Great question. Here are some scenarios where it really shines:
Data Validation Done Right
You can use Proxies to enforce data validation rules. No more invalid data sneaking into your app and causing headaches later.
const person = { name: "", age: 0 };
const handler = {
set(target, prop, value) {
if (prop === "age" && typeof value !== "number") {
throw new TypeError("Age must be a number");
}
target[prop] = value;
return true;
}
};
const personProxy = new Proxy(person, handler);
personProxy.age = 30; // All good
personProxy.age = "thirty"; // Throws an error
Now you’ve got some nice validation that can be extended, and you didn’t have to write a ton of boilerplate code. Nice!
Building Reactive Objects (Yeah, Vue Does This)
If you’ve ever worked with Vue, you’ve already seen Proxies in action. Vue uses Proxies to make data reactive, automatically updating the UI when data changes.
You can use a Proxy to watch objects for changes and react in real-time — perfect for building your own reactive systems or dashboards.
Lazy Objects: Only Create What You Need
You can use a Proxy to defer the creation of expensive objects until they’re actually needed. This is called lazy initialization. Instead of loading all your data up front, you only grab what’s required, when it’s required.
Okay, But What About Reflect?
The Reflect API is like Proxy’s best buddy. While Proxy lets you intercept operations, Reflect gives you tools to work with those operations in a more standardized way. It lets you handle object operations (like setting or getting properties) more cleanly and predictably.
Here’s how you can use Reflect to work with default object behaviors:
const user = { name: "Alice", age: 25 };
console.log(Reflect.get(user, "name")); // Alice
Reflect.set(user, "age", 30); // Sets age to 30
Why bother with Reflect? It makes code easier to read and more consistent. You can use it with Proxies to handle default behavior when you don’t want to do anything custom.
How Proxy and Reflect are the Perfect Duo
Let’s put Proxy and Reflect together. If you want to add some logging but still handle object operations normally, Reflect is your friend. Here’s an example where we log when properties are accessed or changed but delegate the actual work to Reflect:
const product = { name: "Laptop", price: 1000 };
const handler = {
set(target, prop, value) {
console.log(`Setting ${prop} to ${value}`);
return Reflect.set(target, prop, value);
},
get(target, prop) {
console.log(`Getting ${prop}`);
return Reflect.get(target, prop);
}
};
const productProxy = new Proxy(product, handler);
productProxy.price = 1200; // Logs: Setting price to 1200
console.log(productProxy.price); // Logs: Getting price, Output: 1200
The best part? We can customize the behavior (logging), but Reflect handles the actual logic of setting and getting properties. This keeps things simple and predictable.
Why You’ll Love Proxy & Reflect
Here’s why these tools are awesome:
Flexibility: You can control how objects behave, whether you’re adding validation, logging, or lazy loading.
Powerful Abstractions: With Proxies, you can hide complex logic and make it feel like magic. Combine that with Reflect, and you’ve got control and safety.
Cleaner Code: Instead of hacking around edge cases or writing tons of conditionals, Proxies allow you to intercept behavior in a clean and reusable way.
Better DX (Developer Experience): Less boilerplate, fewer surprises, more control. What’s not to love?
Wrapping It Up
And there you have it! Proxies and Reflect may seem a little intimidating at first, but once you get the hang of them, they can dramatically improve your code. Whether you’re validating data, tracking object changes, or just wanting more control over how objects behave, these tools are here to make your life easier.
So go ahead, give them a try! You might just find yourself reaching for Proxy and Reflect in your next project.
Subscribe to my newsletter
Read articles from David Lawrence directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by