标签:JavaScript、设计模式、代理模式、前端进阶
在编程世界里,设计模式是前人总结出的“最佳实践”。今天,我们不讲枯燥的理论,而是通过一个浪漫又有趣的场景——“送花”,来深入理解 JavaScript 中的 代理模式(Proxy Pattern) 。
我们将用一个“肖楚南追小美”的故事,带你掌握代理模式的核心思想,并结合你熟悉的 对象字面量、函数、异步 等知识,写出更优雅、可维护的代码。
🌱 故事背景:送花的烦恼
假设我们有这样一个场景:
let xcNan = {
name: '肖楚南',
hobbies: ['学习', '乒乓球'],
sendFlower: function(target) {
target.receiveFlower(xcNan);
}
};
let xm = {
xq: 30, // 心情值
name: '小美',
receiveFlower: function(sender) {
console.log('小美收到了花', sender.name + '送的花');
if (this.xq < 80) {
console.log('不约,我们不约');
} else {
console.log('硕果走一波!!!');
}
}
};
现在,肖楚南想给小美送花,于是他直接调用:
xcNan.sendFlower(xm);
// 输出:小美收到了花 肖楚南送的花
// 不约,我们不约
结果很惨淡,因为小美心情值只有 30,根本不想理他。
🤔 问题来了:能不能“代理”送花?
肖楚南很苦恼:我直接送花,小美不理我。有没有人能帮我“代理”一下,先提升她的心情,再送花?
这时,代理模式就派上用场了!
✅ 什么是代理模式?
代理模式(Proxy Pattern) :为一个对象提供一个替身,以控制对原对象的访问。代理对象在客户端和目标对象之间起到中介作用。
在我们这个场景中:
- 目标对象:小美(
xm) - 客户端:肖楚南(
xcNan) - 代理对象:小红(
xh)——她可以先“调节气氛”,再帮肖楚南送花。
💡 用“小红”实现代理模式
我们让小红作为“情感代理”,她在收到花后,先等 3 秒钟(模拟调节气氛),把小美心情值提升到 90,再帮肖楚南送花:
let xh = {
name: '小红',
receiveFlower: function(sender) {
console.log('小红收到了', sender.name + '送的花');
// 代理逻辑:先提升小美心情
setTimeout(() => {
xm.xq = 90;
console.log('小红:我已经把小美心情调到90了!');
// 代理执行:帮肖楚南完成送花
xm.receiveFlower(sender);
}, 3000);
}
};
现在,肖楚南不再直接送花给小美,而是送给小红(代理):
xcNan.sendFlower(xh); // 注意:这里传的是 xh,不是 xm
输出结果:
小红收到了 肖楚南送的花
(等待3秒...)
小红:我已经把小美心情调到90了!
小美收到了花 肖楚南送的花
硕果走一波!!!
🎉 成功了!通过“代理”,肖楚南终于打动了小美。
🔍 代理模式的核心优势
- 控制访问:不直接暴露目标对象(小美),而是通过代理(小红)进行访问。
- 增强功能:代理可以在真正操作前/后添加额外逻辑(如延时、验证、缓存等)。
- 解耦:发送者(肖楚南)不需要知道“如何提升心情”,只需关心“送花”这个动作。
🛠️ 更优雅的写法:使用 ES6 Proxy
JavaScript 提供了原生的 Proxy 对象,可以更灵活地实现代理模式。
我们可以用 Proxy 来代理“小美”的 receiveFlower 方法:
let xmProxy = new Proxy(xm, {
get(target, property) {
if (property === 'receiveFlower') {
return function(sender) {
console.log(`【代理拦截】${sender.name} 想给小美送花`);
setTimeout(() => {
xm.xq = 90; // 提升心情
console.log('心情已提升至90!');
target.receiveFlower(sender);
}, 2000);
};
}
return target[property];
}
});
现在,肖楚南可以直接“送花”给代理对象:
xcNan.sendFlower(xmProxy);
输出:
【代理拦截】肖楚南 想给小美送花
(等待2秒...)
心情已提升至90!
小美收到了花 肖楚南送的花
硕果走一波!!!
✅ 这就是
Proxy的强大之处:无需修改原对象,就能拦截和增强其行为。
🧩 代理模式的常见应用场景
| 场景 | 说明 |
|---|---|
| 图片懒加载 | 用 Proxy 控制图片加载时机 |
| 权限控制 | 代理用户操作,检查权限后再执行 |
| 缓存代理 | 代理函数调用,缓存结果避免重复计算 |
| 日志记录 | 代理方法调用,自动记录日志 |
| 防抖/节流 | 代理事件处理函数,控制触发频率 |
📌 总结
通过“送花”这个生活化场景,我们理解了:
- 代理模式的核心是 “用代理对象代替真实对象”
- 代理可以在不修改原对象的前提下,增强功能、控制访问
- JavaScript 的
Proxy是实现代理模式的利器 - 设计模式不是“炫技”,而是为了解决实际问题
💬 编程如人生,有时候直接追求未必成功,找个“代理”迂回一下,反而柳暗花明。
🎁 课后思考
- 如果小红自己也喜欢肖楚南,她会不会“截胡”送花?如何用代理模式实现“情感竞争”?
- 能否用
Proxy实现一个“防抖代理”,避免频繁送花?
欢迎在评论区留下你的想法!