JavaScript代理模式实战:5个高级应用场景解析
1. 属性访问控制
实现私有属性保护:
const createPrivateObject = (target, privateProps) => {
return new Proxy(target, {
get(obj, prop) {
if (privateProps.includes(prop)) {
throw new Error(`无法访问私有属性: ${prop}`);
}
return obj[prop];
},
set(obj, prop, value) {
if (privateProps.includes(prop)) {
throw new Error(`无法修改私有属性: ${prop}`);
}
obj[prop] = value;
return true;
}
});
};
const user = createPrivateObject(
{ name: 'Alice', _password: '123456' },
['_password']
);
console.log(user.name); // "Alice"
// console.log(user._password); // 抛出错误
2. 数据验证代理
实现自动数据校验:
const createValidatedObject = (schema) => {
return new Proxy({}, {
set(obj, prop, value) {
if (schema[prop] && !schema[prop](value)) {
throw new Error(`无效的${prop}值: ${value}`);
}
obj[prop] = value;
return true;
}
});
};
const userSchema = {
age: v => Number.isInteger(v) && v >= 0,
email: v => /^[^s@]+@[^s@]+.[^s@]+$/.test(v)
};
const validatedUser = createValidatedObject(userSchema);
validatedUser.age = 25; // 成功
// validatedUser.age = -5; // 抛出错误
3. 数组负索引支持
扩展数组功能:
const createNegativeArray = (array) => {
return new Proxy(array, {
get(target, prop) {
if (typeof prop === 'string' && /^-?d+$/.test(prop)) {
const index = parseInt(prop);
return target[index < 0 ? target.length + index : index];
}
return target[prop];
}
});
};
const arr = createNegativeArray(['a', 'b', 'c', 'd']);
console.log(arr[-1]); // "d"
4. 函数调用日志
自动记录函数调用:
function withLogging(fn) {
return new Proxy(fn, {
apply(target, thisArg, args) {
console.log(`调用函数: ${target.name}, 参数: ${args}`);
const result = target.apply(thisArg, args);
console.log(`返回结果: ${result}`);
return result;
}
});
}
const sum = withLogging((a, b) => a + b);
sum(2, 3); // 输出调用日志
应用场景 | 传统实现 | Proxy实现 |
---|---|---|
属性控制 | 需手动检查 | 自动拦截 |
数据验证 | 显式校验 | 透明校验 |
功能扩展 | 修改原型 | 无侵入扩展 |
5. 缓存代理模式
实现函数结果缓存:
function createCacheProxy(fn) {
const cache = new Map();
return new Proxy(fn, {
apply(target, thisArg, args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
console.log('从缓存获取结果');
return cache.get(key);
}
const result = target.apply(thisArg, args);
cache.set(key, result);
return result;
}
});
}
const heavyCompute = createCacheProxy((n) => {
// 模拟复杂计算
return n * n;
});
console.log(heavyCompute(5)); // 计算
console.log(heavyCompute(5)); // 从缓存获取
通过合理使用Proxy对象,可以大幅提升JavaScript代码的灵活性和可维护性,实现传统方式难以完成的高级功能。