set methods for object properties, which was an awesome step, but there was still room for improvement.
Proxy accepts an object to proxy for and an object with handlers (“traps”) for
has and other common object methods:
const proxy = new Proxy(, get: (obj, prop) => ... , set: (obj, prop, value) => ... , // more props here );
Any attempt to set or get a property is run through the trap, allowing you to run additional logic, especially if the property is unwanted, doesn’t exist, or requires validation.
Let’s create a basic proxy that returns defaults for any given property:
const proxy = new Proxy(, get: (obj, prop) => return prop in obj ? obj[prop] : null; ); // proxy.whatever => null
The example above illustrates that no matter the property the code attempts to set, your Proxy logic can capture and modify it as desired. Instead of
undefined being returned for a property that doesn’t exist, you can instead return
The most obvious and useful usage of Proxy is validation; since you monitor validate any property coming in, you can keep your data as pure as possible.
const proxy = new Proxy(, set: (obj, prop, value) => // Don't allow age > 100 if (prop === "age" && value > 100) // Set to max age value = 100; obj[prop] = value; ); proxy.age = 120; proxy.age; // 100
You can choose to modify incoming data like the example above, or you can throw an error:
const proxy = new Proxy(, set: (obj, prop, value) => // Ensure age is of type Number if (prop === "age" && isNaN(value)) throw new Error("Invalid age value!"); return; obj[prop] = value; ); proxy.age = "yes"; // Uncaught error: Invalid age value!
You can even use Proxy to provide yourself debugging points or events to see how and when values are being set and retrieved:
const proxy = new Proxy(, set: (obj, prop, value) => console.log(`Setting $prop from $obj[prop] to $value`); obj[prop] = value; ); proxy.prop = 1; proxy.prop = 2; // Setting prop from undefined to 1 // Setting prop from 1 to 2
Even if you don’t modify any input or output, having a hook to value changes on an object is incredibly valuable.
Another simple usage is formatting data that comes into the object:
const proxy = new Proxy(, set: (obj, prop, value) => if (prop === "age") obj[prop] = Number(value); ); proxy.prop = "1"; // 1
You can format from String to Number, Number to String, or simply set defaults.
Using Proxies with Existing Objects
In the examples provided above, we use an empty object (
), but you can also use an existing object:
const myObj = x: "x", y: "y" ; // Use existing object, simply set value as is given const proxy = new Proxy(myObj, set: (obj, prop, value) => obj[prop] = value; ); // proxy.x = "XXX"; proxy.x; // "XXX" myObj.x; // "XXX"
Note that the original object does change, as well as the proxy, so the proxy does not act as a “copy”, so to speak.