Proxy objects were unknown territory for me just a little while ago. I had never even heard of them until I was asked to explain how to use them over on TikTok. I've spent some time now reading up on how to create proxy objects and how they can be used. I'm going to try my best to keep this brief so this won't be a comprehensive guide on how to use proxy objects. This will however show you some of the basic ways you can use them, as well as provide a few examples.
Creating a Proxy Object
To create a proxy object you'll need two things first, a target object and a handler object. The target is the object you're wanting to make the proxy for and the handler is where you define what behavior to change and how it should be changed. After defining both of those objects, you can create the proxy by creating a variable set equal to new Proxy(target, handler)
replacing target and handler with whatever you've named them.
const target = {
greetingOne: "hello",
greetingTwo: "world",
};
const handler = {};
const proxy = new Proxy(target, handler);
I've left the handler empty for now, meaning that there won't be any changes in behavior. This isn't very useful, so next we'll start looking at how we can change some of the behavior of the proxy.
Changing The Get Method
Let's say that we want our proxy to change greetingTwo
to 'dev.to' if target.greetingTwo
is equal to 'world'. To do this, we'll redefine the get method in our handler object to overwrite the normal behavior. We'll need to pass target, prop and receiver into a get()
function and then use those parameters to change the behavior.
const target = {
greetingOne: "hello",
greetingTwo: "world",
};
const handler = {
get(target, prop, receiver) {
if (prop === "greetingTwo") {
return "dev.to";
}
return Reflect.get(...arguments);
},
};
const proxy = new Proxy(target, handler);
console.log(proxy.greetingTwo); // dev.to
Using Reflect
we can keep the original behavior for some of the accessors and only change the values we're wanting to change.
Changing The Set Method
What if we only want certain values to be valid on an object? In order to accomplish this, we can use set()
in our handler. This time we'll pass in an object, prop and value and use the parameters to make sure our data is valid.
const target = {
value: 1,
};
const handler = {
set(obj, prop, value) {
if (prop === "value" && value < 1) {
console.log("value cannot be lower than 1");
// handle error
} else {
return Reflect.set(...arguments);
}
},
};
const proxy = new Proxy(target, handler);
proxy.value = 0; // 'value cannot be lower than 1'
console.log(proxy.value); // 1
proxy.value = 3;
console.log(proxy.value); // 3
Again, using Reflect
let's us keep the normal behavior if we want it. Attempting to set proxy.value
to a number less than 1 will result in a warning being console logged and the value not being set. Values 1 and higher are still valid.
Intercepting other methods
In hopes of keeping this post short and concise I'm not going to cover each individual handler trap. There are eleven more, but I'll only be showing a few. MDN has examples for all of them, and I would reccomend giving the docs a quick read if you're looking for more examples and a more thorough explanation.
-
apply()
- Using
apply()
traps function calls. - Using a function as your target object, and calling
apply()
like this:
- Using
apply: function(target, thisArg, argList){}
you can add onto existing functions, changing how a function behaves.
-
construct()
- Using
construct(target, args)
traps the 'new' keyword. - You're then able the change the behavior of constructing new objects
- Using
-
has()
- Using
has(target, key)
is a trap for thein
operator - You're then able to change the behavior of how keys are accessed through the
in
operator like this
- Using
if (key === "keyOne") {
return false;
}
return key in target;
-
deleteProperty()
- Using
deleteProperty(target, property)
traps thedelete
operator - This will allow you to change how properties get deleted, allowing for conditions to be set
- Using
delete proxy.keyOne; // gets trapped in the handler object
That's going to do it for this post, If you have any questions I'll do my best to answer them in the comments.
Top comments (1)
Nice explanation, thank you for sharing! 😁