js代理实现
代理模式的概念
代理模式是一种设计模式,为其他对象提供一种代理以控制对这个对象的访问。在JavaScript中,代理通常用于拦截和自定义对象的基本操作。
Proxy对象的基本使用
JavaScript提供了内置的Proxy对象,可以用来创建对象的代理。Proxy构造函数接受两个参数:目标对象和处理程序对象。
const target = {};
const handler = {
get: function(target, prop, receiver) {
return Reflect.get(...arguments);
}
};
const proxy = new Proxy(target, handler);
常见的代理拦截操作
代理可以拦截多种基本操作,以下是常见的几种拦截器:
get拦截器 用于拦截对象属性的读取操作。

const handler = {
get: function(target, prop) {
return prop in target ? target[prop] : 'default';
}
};
set拦截器 用于拦截对象属性的设置操作。
const handler = {
set: function(target, prop, value) {
if (prop === 'age' && typeof value !== 'number') {
throw new Error('Age must be a number');
}
target[prop] = value;
return true;
}
};
has拦截器 用于拦截in操作符。
const handler = {
has: function(target, prop) {
return prop.startsWith('_') ? false : prop in target;
}
};
实现数据验证
代理可以用于实现数据验证,确保对象属性的值符合特定要求。

const validator = {
set: function(obj, prop, value) {
if (prop === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('Age must be an integer');
}
if (value < 0) {
throw new RangeError('Age must be positive');
}
}
obj[prop] = value;
return true;
}
};
实现私有属性
通过代理可以实现类似私有属性的功能,阻止对特定前缀属性的访问。
const privateHandler = {
get: function(target, prop) {
if (prop.startsWith('_')) {
throw new Error('Cannot access private property');
}
return target[prop];
},
set: function(target, prop, value) {
if (prop.startsWith('_')) {
throw new Error('Cannot set private property');
}
target[prop] = value;
return true;
}
};
实现函数代理
代理不仅可以用于对象,还可以用于函数,拦截函数的调用操作。
function wrap(target) {
return new Proxy(target, {
apply: function(target, thisArg, argumentsList) {
console.log('Function called with args:', argumentsList);
return target.apply(thisArg, argumentsList);
}
});
}
实现缓存代理
代理可以用于实现缓存功能,避免重复计算。
function createCacheProxy(fn) {
const cache = new Map();
return new Proxy(fn, {
apply: function(target, thisArg, args) {
const key = args.join('-');
if (cache.has(key)) {
return cache.get(key);
}
const result = target.apply(thisArg, args);
cache.set(key, result);
return result;
}
});
}
注意事项
使用Proxy时需要注意浏览器兼容性问题,Proxy是ES6特性,不支持IE浏览器。代理的性能开销比直接操作对象要大,在性能敏感的场景需要谨慎使用。






