JavaScript 代理模式与发布订阅模式实战解析
本文深入解析JavaScript中的代理模式与发布订阅模式。通过虚拟代理实现图片预加载,利用缓存代理优化重复计算性能,并基于数组操作实现发布订阅机制。文章提供完整代码示例与运行结果,帮助开发者理解核心原理及实际应用。
JavaScript代理模式与发布订阅模式实战解析
本文通过具体实例详细讲解JavaScript中的代理模式与发布订阅模式,旨在为读者提供参考并辅助学习。
将这两种设计模式合并在同一篇文章中讨论,主要是为了保持内容的连贯性与篇幅的完整性。
撰写技术博客的首要目标在于梳理个人知识体系,通过用自己的语言重新阐述概念,将外部知识内化为个人能力。
本文为设计模式系列的第二篇内容,第一篇内容可参考相关历史文章。
代理模式:虚拟与缓存实现
1,代理模式,仅学习了虚拟代理以及缓存代理,具体案例
1)虚拟代理应用场景解析
//业务代码
var myImage = (function() {
var imgNode = document.createElement("img");
document.body.appendChild(imgNode);
return {
setSrc: function(src) {
console.log(1111);
imgNode.src = src;
}
}
})();
// 设计模式代码
var ProxyImage = (function() {
var img = new Image();
//这个img只是用来判断图片是否加载完成,加载完成之后修改图片链接
img.onload = function() {
console.log(this);
myImage.setSrc(this.src);
};
return {
setSrc: function(src) {
console.log(22);
myImage.setSrc("http://img.lanrentuku.com/img/allimg/1212/5-121204193Q9-50.gif");
img.src = src;
}
}
})();
该示例借鉴了经典实现思路。核心业务逻辑是将图片DOM节点插入文档树,而代理模式则通过创建一个隐藏的Image对象来监听加载状态(onload)。当图片加载完成后,代理对象将替换原始图片的链接,从而优化用户体验。
2)缓存代理实现示例
<script>
//缓存代理
// 计算乘法
var mult = function() {
var a = 1;
for (var i = 0, ilen = arguments.length; i < ilen; i += 1) {
a = a * arguments[i];
}
return a;
};
// 代理函数
var proxyFunc = function(fn) {
var cache = {}; // 缓存对象
return function() {
//利用闭包
var args = Array.prototype.join.call(arguments);
if (args in cache) {
return cache[args]; // 使用缓存代理
}
return cache[args] = fn.apply(this, arguments);
}
};
var proxyMult = proxyFunc(mult);
console.log(proxyMult(1, 2, 3, 4)); // 24
console.log(proxyMult(1, 2, 3, 4)); // 缓存取 24
</script>
代码运行后的输出结果如下所示。

该方案利用闭包特性,将计算结果存储在缓存对象中,从而避免重复执行昂贵的计算过程。
发布订阅模式核心机制
2,订阅发布模式(Pub/Sub)
<script>
var Event = (function(){
var list = {},
listen,
trigger,
remove;
//添加订阅对象
listen = function(key,fn){
if(!list[key]) {
list[key] = [];
}
list[key].push(fn);
};
//触发订阅内容
trigger = function(){
var key = Array.prototype.shift.call(arguments),
fns = list[key];
if(!fns || fns.length === 0) {
return false;
}
for(var i = 0, fn; fn = fns[i++];) {
fn.apply(this,arguments);
}
};
//删除订阅内容
remove = function(key,fn){
var fns = list[key];
if(!fns) {
return false;
}
if(!fn) {
fns && (fns.length = 0);
}else {
for(var i = fns.length - 1; i >= 0; i--){
var _fn = fns[i];
if(_fn === fn) {
fns.splice(i,1);
}
}
}
};
return {
listen: listen,
trigger: trigger,
remove: remove
}
})();
// 测试代码如下:
Event.listen("color",function(size) {
console.log("尺码为:"+size); // 打印出尺码为42
});
Event.trigger("color",42);
</script>
该模式的运行结果展示如下。

从本质上看,发布订阅模式是对数组进行增删改查操作的封装。其核心逻辑在于维护一个事件列表,实现事件的注册与触发。
本文内容到此结束。
感兴趣的用户可以使用在线HTML/CSS/JavaScript前端代码调试运行工具:http://tools.jb51.net/code/WebCodeRun 来测试上述代码的实际运行效果。
如需了解更多JavaScript相关知识,建议查阅本站系列教程,包括《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》。
希望本文关于JavaScript程序设计的阐述能对大家的技术实践有所帮助。
什么时候该用JS构造器:与工厂模式、字面量的选择对比
2026-11-05 16:18:22
推荐几款轻量级JS照片墙开源库及对比
2026-11-05 15:56:19
JavaScript递归写法有哪些常见陷阱及避免方法
2026-11-05 14:53:38
JS数组浅拷贝与深拷贝怎么选?场景与方法总结
2026-11-05 14:41:02
p5.js 中 setup() 和 draw() 函数的执行机制详解
2026-11-05 12:32:38
