JavaScript设计模式详解:虚拟代理与缓存代理实战

作者:听澜

时间:2026-10-30

浏览:133

本文深入解析JavaScript中的代理模式,重点介绍虚拟代理与缓存代理两种核心应用。通过图片预加载、HTTP请求合并及计算结果缓存等实际代码示例,展示如何利用代理对象控制访问、延迟创建及复用计算结果,从而提升前端应用的性能与代码结构的清晰度。

文章目录

代理模式概述

代理模式的核心在于为某个对象提供一个替代者或占位符,以此控制对该对象的直接访问。从实际开发角度看,这种模式的主要价值在于保障当前对象的单一职责。通过引入另一个对象来处理调用原对象前的前置逻辑,如状态判断或效率优化,可以有效提升代码的独立性与运行效率。在JavaScript中,虚拟代理和缓存代理是应用最为广泛的两种形式。

虚拟代理:延迟加载与请求合并

一、虚拟代理 虚拟代理的主要作用是将那些创建或执行成本较高的对象,延迟到真正需要使用它们时才进行初始化。这种策略特别适用于资源消耗巨大的场景。


// 图片加载函数
var myImage = (function(){
  var imgNode = document.createElement("img");
  document.body.appendChild(imgNode);

  return {
    setSrc: function(src) {
      imgNode.src = src;
    }
  }
})();

// 引入代理对象
var proxyImage = (function(){
  var img = new Image;
  img.onload = function(){
    // 图片加载完成,正式加载图片
    myImage.setSrc( this.src );
  };
  return {
    setSrc: function(src){
      // 图片未被载入时,加载一张提示图片
      myImage.setSrc("file://c:/loading.png");
      img.src = src;
    }
  }
})();

// 调用代理对象加载图片
proxyImage.setSrc( "http://images/qq.jpg");

示例: 虚拟代理合并HTTP请求 假设某个功能需要频繁发起网络请求,这会带来显著的性能开销。一种高效的解决方案是引入代理函数,在一段时间内收集多个请求,然后一次性发送给服务器。例如,在实现文件同步功能时,当用户选中一个文件,代理对象会负责将其同步至另一台备用服务器,同时优化请求频率。


// 文件同步函数
var synchronousFile = function( id ){
  console.log( "开始同步文件,id为:" + id );
}
// 使用代理合并请求
var proxySynchronousFile = (function(){
  var cache = [], // 保存一段时间内需要同步的ID
    timer; // 定时器指针

  return function( id ){
    cache[cache.length] = id;
    if( timer ){
      return;
    }

    timer = setTimeout( function(){
      proxySynchronousFile( cache.join( "," ) ); // 2s 后向本体发送需要同步的ID集合
      clearTimeout( timer ); // 清空定时器
      timer = null;
      cache = []; // 晴空定时器
    },2000 );
  }
})();

// 绑定点击事件
var checkbox = document.getElementsByTagName( "input" );

for(var i= 0, c; c = checkbox[i++]; ){
  c.onclick = function(){
    if( this.checked === true ){
      // 使用代理进行文件同步
      proxySynchronousFile( this.id );
    }
  }
}

缓存代理:结果复用

二、 缓存代理 缓存代理旨在为计算开销较大的运算结果提供临时存储。当下次传入相同的参数时,代理可以直接返回之前缓存的计算结果,从而避免重复计算。


// 计算乘积
var mult = function(){
  var a = 1;
  for( var i = 0, l = arguments.length; i < l; i++){
    a = a * arguments[i];
  }
  return a;
};
// 计算加和
var plus = function () {
 var a = 0;
  for( var i = 0, l = arguments.length; i < l; i++ ){
    a += arguments[i];
  }
  return a;
};
// 创建缓存代理的工厂
var createProxyFactory = function( fn ){
  var cache = {}; // 缓存 - 存放参数和计算后的值
  return function(){
    var args = Array.prototype.join.call(arguments, "-");
    if( args in cache ){ // 判断出入的参数是否被计算过
      console.log( "使用缓存代理" );
      return cache[args];
    }
    return cache[args] = fn.apply( this, arguments );
  }
};
// 创建代理
var proxyMult = createProxyFactory( mult ),
  proxyPlus = createProxyFactory( plus );

console.log( proxyMult( 1, 2, 3, 4 ) ); // 输出: 24
console.log( proxyMult( 1, 2, 3, 4 ) ); // 输出: 缓存代理 24
console.log( proxyPlus( 1, 2, 3, 4 ) ); // 输出: 10
console.log( proxyPlus( 1, 2, 3, 4 ) ); // 输出: 缓存代理 10

上述三个示例详细阐述了JavaScript中代理模式的具体应用场景,希望这些内容能对读者的学习与实践提供有益的帮助。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章