Proxy – Taking Control Over Objects
Since the introduction of ES6, JavaScript has received many new features that offer developers more control and flexibility. One of these powerful tools is the Proxy. With Proxies, you can intercept and customize the behavior of objects by influencing fundamental operations like reading, writing, or deleting properties.
What is a Proxy?
A Proxy is a wrapper object that represents a target object and allows you to monitor and modify basic object operations. This is done through so-called handlers, which provide functions to intercept various actions, such as accessing properties or calling methods.
Basic Syntax
Creating a Proxy is done with the Proxy constructor, which accepts two arguments:
- Target object (target): The original object that the Proxy wraps.
- Handler: An object with “traps” that intercept operations.
Example:
const targetObject = {};
const handler = {
get: function(target, property, receiver) {
console.log(`Property ${property} was read.`);
return target[property];
}
};
const proxy = new Proxy(targetObject, handler);
proxy.name = 'Max';
console.log(proxy.name);
// Output:
// Property name was read.
// Max
Common Traps
1. get Trap – Intercepting Property Access:
const person = {
name: 'Anna',
age: 30
};
const handler = {
get(target, property) {
if (property in target) {
return target[property];
} else {
console.log(`Property ${property} does not exist.`);
return undefined;
}
}
};
const proxy = new Proxy(person, handler);
console.log(proxy.name); // Anna
console.log(proxy.email); // Property email does not exist.
2. set Trap – Validating Values:
const user = {};
const handler = {
set(target, property, value) {
if (property === 'age') {
if (typeof value !== 'number') {
throw new TypeError('Age must be a number.');
}
if (value < 0) {
throw new RangeError('Age must be positive.');
}
}
target[property] = value;
return true;
}
};
const proxy = new Proxy(user, handler);
proxy.age = 25; // OK
proxy.age = -5; // Error: Age must be positive.
3. has Trap – Controlling in Operator:
const secretData = {
secret: 'classified',
public: 'available'
};
const handler = {
has(target, property) {
if (property.startsWith('secret')) {
return false;
}
return property in target;
}
};
const proxy = new Proxy(secretData, handler);
console.log('public' in proxy); // true
console.log('secret' in proxy); // false
Practical Use Cases
1. Validation:
function createValidator(schema) {
return new Proxy({}, {
set(target, property, value) {
const validator = schema[property];
if (validator && !validator(value)) {
throw new Error(`Invalid value for ${property}`);
}
target[property] = value;
return true;
}
});
}
const userSchema = {
age: value => typeof value === 'number' && value > 0,
name: value => typeof value === 'string' && value.length > 0
};
const user = createValidator(userSchema);
user.name = 'Max'; // OK
user.age = 30; // OK
user.age = -5; // Error: Invalid value for age
2. Logging and Debugging:
function createLoggingProxy(target) {
return new Proxy(target, {
get(target, property) {
console.log(`Reading ${property}`);
return target[property];
},
set(target, property, value) {
console.log(`Setting ${property} to ${value}`);
target[property] = value;
return true;
}
});
}
const obj = createLoggingProxy({ name: 'Test' });
obj.name; // Reading name
obj.value = 42; // Setting value to 42
3. Default Values:
const handler = {
get(target, property) {
return property in target ? target[property] : 'N/A';
}
};
const data = new Proxy({}, handler);
data.name = 'Max';
console.log(data.name); // Max
console.log(data.age); // N/A
Conclusion
Proxies are a powerful feature in JavaScript that allow you to control and customize object behavior in ways that were previously impossible. They enable elegant solutions for validation, logging, lazy loading, and many other scenarios. While they are advanced, understanding and using Proxies can significantly enhance your JavaScript development capabilities.
Experiment with Proxies in your next project and discover how they can add new levels of control and flexibility to your code!