Basic methods of creating a Proxy
Basic Concepts of Proxy
The Proxy object is used to define custom behavior for fundamental operations (such as property lookup, assignment, enumeration, function invocation, etc.). It acts as an "interception" layer in front of the target object, where all external access to the object must first pass through this layer.
const target = {};
const handler = {};
const proxy = new Proxy(target, handler);
Basic Syntax for Creating a Proxy
The Proxy constructor takes two parameters:
target
: The target object to wrap (can be any type of object, including native arrays, functions, or even another proxy).handler
: An object whose properties are usually functions that define the behavior of the proxy when various operations are performed.
const handler = {
get(target, prop, receiver) {
return target[prop] * 2;
}
};
const obj = { num: 21 };
const proxy = new Proxy(obj, handler);
console.log(proxy.num); // 42
Common Traps in the Handler Object
get Trap
Intercepts property read operations.
const handler = {
get(target, property) {
return property in target ?
target[property] :
`Property "${property}" does not exist`;
}
};
const proxy = new Proxy({}, handler);
proxy.foo = 'bar';
console.log(proxy.foo); // "bar"
console.log(proxy.baz); // "Property "baz" does not exist"
set Trap
Intercepts property assignment operations.
const validator = {
set(obj, prop, value) {
if (prop === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('Age must be an integer');
}
if (value < 0 || value > 150) {
throw new RangeError('Age must be between 0 and 150');
}
}
obj[prop] = value;
return true;
}
};
const person = new Proxy({}, validator);
person.age = 25; // Works
person.age = 'young'; // Throws TypeError
person.age = 200; // Throws RangeError
apply Trap
Intercepts function calls, call
, and apply
operations.
const handler = {
apply(target, thisArg, argumentsList) {
console.log(`Calling function with args: ${argumentsList}`);
return target(...argumentsList) * 2;
}
};
function sum(a, b) {
return a + b;
}
const proxy = new Proxy(sum, handler);
console.log(proxy(1, 2));
// Output: Calling function with args: 1,2
// Output: 6
construct Trap
Intercepts the new
operator.
class Person {
constructor(name) {
this.name = name;
}
}
const handler = {
construct(target, args, newTarget) {
console.log(`Creating instance with name: ${args[0]}`);
return new target(...args);
}
};
const PersonProxy = new Proxy(Person, handler);
const p = new PersonProxy('John');
// Output: Creating instance with name: John
console.log(p.name); // "John"
Revocable Proxy Functionality
The Proxy.revocable()
method can be used to create a revocable proxy object.
const {proxy, revoke} = Proxy.revocable({}, {
get(target, prop) {
return `Intercepted: ${prop}`;
}
});
console.log(proxy.foo); // "Intercepted: foo"
revoke();
console.log(proxy.foo); // TypeError: Cannot perform 'get' on a proxy that has been revoked
Practical Application Examples
Implementing Data Validation
const userValidator = {
set(target, prop, value) {
if (prop === 'email') {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
throw new Error('Invalid email format');
}
}
if (prop === 'password' && value.length < 8) {
throw new Error('Password must be at least 8 characters');
}
target[prop] = value;
return true;
}
};
const user = new Proxy({}, userValidator);
user.email = 'test@example.com'; // Works
user.password = '12345678'; // Works
user.email = 'invalid-email'; // Throws Error
Implementing Auto-Filling Objects
const autoFillHandler = {
get(target, prop) {
if (!(prop in target)) {
target[prop] = {};
}
return target[prop];
}
};
const config = new Proxy({}, autoFillHandler);
config.database.host = 'localhost';
config.database.port = 3306;
config.api.endpoint = '/api/v1';
console.log(config);
// Output: { database: { host: 'localhost', port: 3306 }, api: { endpoint: '/api/v1' } }
Implementing Negative Array Indices
const negativeArrayHandler = {
get(target, prop, receiver) {
const index = parseInt(prop);
if (index < 0) {
prop = String(target.length + index);
}
return Reflect.get(target, prop, receiver);
}
};
function createNegativeArray(array) {
return new Proxy(array, negativeArrayHandler);
}
const arr = createNegativeArray(['a', 'b', 'c', 'd']);
console.log(arr[-1]); // "d"
console.log(arr[-2]); // "c"
Limitations of Proxy
- Cannot proxy primitive values (numbers, strings, booleans, etc.).
- Some internal properties of built-in objects cannot be proxied.
- Performance overhead is higher than direct object operations.
- Cannot modify certain non-configurable properties.
// Attempting to proxy a primitive value throws a TypeError
const proxy = new Proxy(42, {}); // TypeError: Cannot create proxy with a non-object as target
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:实际应用场景
下一篇:Proxy的捕获器(trap)