JavaScript系列(75)--代理模式专题
- 开源代码
- 2025-08-30 19:54:02

JavaScript代理模式专题 🎭
JavaScript的Proxy提供了强大的对象代理能力,能够拦截和自定义对象的基本操作。本文将深入探讨Proxy的各种模式、应用场景和最佳实践。
代理基础 🌟💡 小知识:代理模式允许我们创建一个对象的代理,从而可以控制对这个对象的访问。JavaScript的Proxy API提供了13种基本操作的拦截器(trap),使我们能够自定义对象的行为。
// 基础代理操作 const target = { name: '张三', age: 25 }; const handler = { get(target, property) { console.log(`访问属性: ${property}`); return target[property]; }, set(target, property, value) { console.log(`设置属性: ${property} = ${value}`); target[property] = value; return true; } }; const proxy = new Proxy(target, handler); console.log(proxy.name); // 输出: 访问属性: name 然后是 "张三" proxy.age = 26; // 输出: 设置属性: age = 26 Proxy拦截器详解 📋 1. 基本拦截器 class BasicTraps { static demonstrateBasicTraps() { const handler = { // 属性读取拦截 get(target, prop, receiver) { return Reflect.get(target, prop, receiver); }, // 属性设置拦截 set(target, prop, value, receiver) { return Reflect.set(target, prop, value, receiver); }, // 属性删除拦截 deleteProperty(target, prop) { return Reflect.deleteProperty(target, prop); }, // 属性存在性检查拦截 has(target, prop) { return Reflect.has(target, prop); } }; return new Proxy({}, handler); } } 2. 高级拦截器 class AdvancedTraps { static demonstrateAdvancedTraps() { const handler = { // 对象属性枚举拦截 ownKeys(target) { return Reflect.ownKeys(target); }, // 属性描述符获取拦截 getOwnPropertyDescriptor(target, prop) { return Reflect.getOwnPropertyDescriptor(target, prop); }, // 原型获取拦截 getPrototypeOf(target) { return Reflect.getPrototypeOf(target); }, // 原型设置拦截 setPrototypeOf(target, proto) { return Reflect.setPrototypeOf(target, proto); } }; return new Proxy({}, handler); } } 3. 函数和构造器拦截 class FunctionTraps { static demonstrateFunctionTraps() { function target(a, b) { return a + b; } const handler = { // 函数调用拦截 apply(target, thisArg, args) { console.log(`调用函数,参数:${args}`); return Reflect.apply(target, thisArg, args); }, // 构造函数调用拦截 construct(target, args, newTarget) { console.log(`构造函数调用,参数:${args}`); return Reflect.construct(target, args, newTarget); } }; return new Proxy(target, handler); } } 常用代理模式 💼 1. 验证代理 class ValidationProxy { static createValidator(validationRules) { return new Proxy({}, { set(target, property, value) { if (validationRules[property]) { const [isValid, message] = validationRules[property](value); if (!isValid) { throw new Error(`验证失败: ${property} - ${message}`); } } return Reflect.set(target, property, value); } }); } } // 使用示例 const userValidator = ValidationProxy.createValidator({ age: (value) => [ Number.isInteger(value) && value >= 0 && value <= 150, '年龄必须是0-150之间的整数' ], email: (value) => [ /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value), '邮箱格式不正确' ] }); 2. 日志代理 class LoggingProxy { static createLogger(target, logCallback = console.log) { return new Proxy(target, { get(target, property) { logCallback(`获取属性: ${property}`); return Reflect.get(target, property); }, set(target, property, value) { logCallback(`设置属性: ${property} = ${value}`); return Reflect.set(target, property, value); }, deleteProperty(target, property) { logCallback(`删除属性: ${property}`); return Reflect.deleteProperty(target, property); } }); } } // 使用示例 const user = LoggingProxy.createLogger({ name: '张三', age: 25 }); 3. 访问控制代理 class AccessControlProxy { static createPrivateProperties(target, privateProps = []) { return new Proxy(target, { get(target, property) { if (privateProps.includes(property)) { throw new Error(`无法访问私有属性: ${property}`); } return Reflect.get(target, property); }, set(target, property, value) { if (privateProps.includes(property)) { throw new Error(`无法修改私有属性: ${property}`); } return Reflect.set(target, property, value); }, deleteProperty(target, property) { if (privateProps.includes(property)) { throw new Error(`无法删除私有属性: ${property}`); } return Reflect.deleteProperty(target, property); } }); } } 4. 缓存代理 class CachingProxy { static createCached(target, ttl = 5000) { const cache = new Map(); return new Proxy(target, { apply(target, thisArg, args) { const key = JSON.stringify(args); const now = Date.now(); if (cache.has(key)) { const [result, timestamp] = cache.get(key); if (now - timestamp < ttl) { return result; } } const result = Reflect.apply(target, thisArg, args); cache.set(key, [result, now]); return result; } }); } } // 使用示例 const expensiveOperation = CachingProxy.createCached( (x, y) => { console.log('执行计算...'); return x + y; } ); 最佳实践 ⭐ 结合Reflect API使用 // 推荐 const handler = { get(target, prop, receiver) { return Reflect.get(target, prop, receiver); } }; // 不推荐 const handler = { get(target, prop) { return target[prop]; } }; 合理使用代理链 function createProxyChain(...handlers) { return (target) => { return handlers.reduce((proxy, handler) => { return new Proxy(proxy, handler); }, target); }; } 错误处理 const handler = { get(target, prop, receiver) { try { return Reflect.get(target, prop, receiver); } catch (error) { console.error(`获取属性 ${prop} 失败:`, error); return undefined; } } }; 性能考虑 ⚡ 避免过度代理 // 不推荐 function createProxy(obj) { return new Proxy(obj, { get: (target, prop) => Reflect.get(target, prop) // 无意义的代理 }); } // 推荐 function createProxy(obj) { return obj; // 如果不需要拦截,直接返回原对象 } 缓存代理结果 class ProxyCache { constructor() { this.cache = new WeakMap(); } createProxy(target, handler) { if (this.cache.has(target)) { return this.cache.get(target); } const proxy = new Proxy(target, handler); this.cache.set(target, proxy); return proxy; } } 合理使用可撤销代理 function createRevocableProxy(target, handler) { const { proxy, revoke } = Proxy.revocable(target, handler); // 在不需要时撤销代理 setTimeout(() => { revoke(); }, 5000); return proxy; } 总结 📝JavaScript的Proxy API提供了:
强大的对象操作拦截能力灵活的代理模式实现方式与Reflect API的完美配合丰富的实际应用场景💡 学习建议:
深入理解各种代理拦截器掌握常用代理模式注意性能影响合理使用代理链始终做好错误处理如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇
终身学习,共同成长。
咱们下一期见
💻
JavaScript系列(75)--代理模式专题由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“JavaScript系列(75)--代理模式专题”