What is a Proxy?
A Proxy in JavaScript is an object that wraps another object (called the target) and intercepts fundamental operations performed on it, such as property access, assignment, and function invocation. By defining custom behavior for these operations, Proxies allows developers to create highly dynamic and flexible applications.
‘In Small terms Proxy is a Wrapper over an object for advanced capability over objects’
Syntax
Creating a Proxy is straightforward. Here’s the basic syntax:
const proxy = new Proxy(target, handler);
target: The object that the proxy will wrap.handler: An object containing traps (functions) that define the custom behavior for various operations.
Traps
Traps are the methods provided in the handler object to intercept operations. Some common traps include:
get: Handles property access.set: Handlesproperty assignment.has: Handles theinoperator.deleteProperty: Handles property deletion.apply: Handles function calls.construct: Handles thenewoperator.
Creating a Simple Proxy
Let’s create a simple proxy to log property access and assignments.
const target = {
name: 'Ishraq',
age: 15
};
const handler = {
get: function(target, property, receiver) {
console.log(`Getting property ${property}`);
return target[property];
},
set: function(target, property, value, receiver) {
console.log(`Setting property ${property} to ${value}`);
target[property] = value;
return true;
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // Logs "Getting property name"
proxy.age = 19; // Logs "Setting property age to 19"
console.log(proxy.age); // Logs "Getting property age"
Validation
Proxies can be used to enforce validation rules on objects. This is especially useful when dealing with user input or API responses. It opens a new layer of validation checking!
const user = {
name: '',
age: 0
};
const handler = {
set: function(target, property, value, receiver) {
if (property === 'age' && (typeof value !== 'number' || value < 0)) {
throw new Error('Age must be a non-negative number');
}
target[property] = value;
return true;
}
};
const proxy = new Proxy(user, handler);
proxy.age = 25; // Works fine
proxy.age = -5; // Throws an error: Age must be a non-negative number
Data Binding
Proxies can be used for data binding in frameworks, allowing automatic updates to the UI when the underlying data changes.
const data = {
text: 'Hello, world!'
};
const handler = {
set: function(target, property, value, receiver) {
target[property] = value;
document.getElementById('output').textContent = value;
return true;
}
};
const proxy = new Proxy(data, handler);
document.getElementById('input').addEventListener('input', function(event) {
proxy.text = event.target.value;
});
‘Currently, I am working on a reactive javascript library focused on speed & efficiency. There I’ve used proxies at great extinct for data binding…I really don’t appreciate the phrase data binding it’s good to tell it reactive data binding.’
Tracing
Proxies can help trace property access and modifications, useful for debugging and profiling. It has a great usage in application testing.
const profile = {
name: 'John Doe',
email: 'john@example.com'
};
const handler = {
get: function(target, property, receiver) {
console.log(`Property ${property} accessed`);
return target[property];
},
set: function(target, property, value, receiver) {
console.log(`Property ${property} set to ${value}`);
target[property] = value;
return true;
}
};
const proxy = new Proxy(profile, handler);
proxy.name; // Logs: Property name accessed
proxy.email = 'john.doe@example.com'; // Logs: Property email set to john.doe@example.com
‘In my reactive framework, I’ve implemented some robust test cases and while testing props of dom elements, I’ve used this for tracking any updates in props, which helped me to reflect any changes in props to the dom elements’
Immutable Objects
Proxies are also used to create immutable objects, where properties cannot be changed once they are set. It’s like object properties but constant type, can’t be changed in any meaning.
const target = {
name: 'Immutable Object'
};
const handler = {
set: function(target, property, value, receiver) {
console.log(`Cannot set property ${property} to ${value}. Object is immutable.`);
return false; // indicate failure to set property
}
};
const proxy = new Proxy(target, handler);
proxy.name = 'New Name'; // Logs: Cannot set property name to New Name. Object is immutable.
console.log(proxy.name); // Logs: Immutable Object
Meta Programming
Meta Programming means to program at the meta-level of JavaScript. JavaScript proxies unlock this meta layer/level of programming to help programmers define custom behaviors. I will publish a very much detailed Post later on about meta programming. But, if you wanna learn about this meta layer of JavaScript check the resources section!
Resources
To further deepen your understanding of JavaScript Proxies and their various applications, here are some valuable resources including meta programming!:
Conclusion
JavaScript Proxies are a powerful feature that allows developers to intercept and redefine fundamental operations on objects. They can be used for a wide range of applications, from validation and data binding to tracing and debugging. My favorite one is data binding. But, other real-world use cases have made it one of the most powerful features ever lived in the JavaScript Ecosystem. By understanding and utilizing Proxies, you can add a new level of dynamism and flexibility to your JavaScript code.