学习JavaScript设计模式之代理模式


Posted in Javascript onJanuary 12, 2016
  • 明星都有经纪人作为代理。如果请明星办一场商演,只能联系其经纪人,经纪人会把商演的细节和报酬谈好,再把合同交给明星签。

一、定义

代理模式:为一个对象提供一个代用品或占位符,以便控制对它的访问。
代理分为:保护代理和虚拟代理
保护代理:用于控制不同权限的对象对目标对象的访问,在JavaScript中很难判断谁访问了某个对象,所以保护代理很难实现。

二、图片预加载(最常见的虚拟代理应用场景)

图片预加载是一种常用技术,如果直接给某个img标签节点设置src属性,由于图片过大或者网络不佳,图片的位置往往有段时间会有空白。常见的做法事先用一张loading图片占位,然后异步加载图片,待图片加载完成,把其填充到img节点里。
实现原理:
创建一个Image对象:var a = new Image();
定义Image对象的src: a.src = “xxx.gif”;
这样做就相当于给浏览器缓存了一张图片。

可通过Image对象的complete属性来检测图像是否加载完成。每个Image对象都有一个complete属性,当图像处于装载过程中时,该属性值false,当发生了onload、onerror、onabort中任何一个事件后,则表示图像装载过程结束,此时complete属性为true。

(1)非代理实现

var myImage = (function() {
  var imgNode = document.createElement("img");
  document.body.appendChild(imgNode);
  var img = new Image();

  img.onload = function() {
    imgNode.src = img.src;
  };

  return {
    setSrc: function(src) {
      imgNode.src = "./images/loading.gif";
      img.src = src;
    }
  }
})();

myImage.setSrc("./images/originImg.png");

(2)代理实现

// 创建图片DOM
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);  // this指向img!img加载完成后,将img.src传递给myImage
  };

  return {
    setSrc: function(src) {
      myImage.setSrc("./images/loading.gif");   // loading
      img.src = src;
    }
  };
})();

proxyImage.setSrc("./images/originImg.png");

使用代理模式的好处:使每个函数功能单一,实现对象设计的“单一职责原则”!

三、文件同步

假设我们在做一个文件同步功能,当选中checkbox时候,它对应的文件就会被同步到另外一台服务器。

<body>
    <input type="checkbox" id="1" />文件1
    <input type="checkbox" id="2" />文件2
    <input type="checkbox" id="3" />文件3
    <input type="checkbox" id="4" />文件4
    <input type="checkbox" id="5" />文件5
    <input type="checkbox" id="6" />文件6
  </body>

没选中一个checkbox就同步一次,显然不太合理。因为在web开发中,最大的开销就是网络请求。
解决方案:通过一个代理函数来收集一段时间之内的请求,然后一次性发给服务器。

var synchronousFile = function(id) {
  console.log("开始同步文件,id为:" + id);
};

var proxySynchonousFile = (function() {
  var cache = [],   // 保存本次需要同步文件的id
    timer;     // 定时器

  return function(id) {
    cache.push(id);
    if(timer) { 
      // 不要覆盖已经启动的定时
      return;
    }

    timer = setTimeout(function(){
      synchronousFile(cache.join(","));
      clearTimeout(timer);
      timer = null;
      cache.length = 0;  // 清空缓存
    }, 2000);
  }
})();

var checkboxs = document.getElementsByTagName("input");

for(var i = 0, c; c = checkboxs[i]; i++) {
  c.onclick = function() {
    if(this.checked === true) {
      proxySynchonousFile(this.id);
    }
  }
}

四、缓存代理?计算乘积(序列一模一样)

var mult = function() {
  var result = 1;
  for(var i = 0, l = arguments.length; i < l; i++) {
    result= result * arguments[i];
  }
  return result;
};

var proxyMult = (function() {
  var cache = {};   // {"1,2,3": 6}
  return function() {
    var args = Array.prototype.join.call(arguments, ",");
    if(args in cache) {
      return cache[args];
    }
    return cache[args] = mult.apply(this, arguments);
  }
})();

console.log(proxyMult(1, 2, 3));

// 改造:

var proxyFactory = 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);
  }  
};

console.log(proxyFactory(mult)(1, 2, 3));

希望本文所述对大家学习javascript程序设计有所帮助。

Javascript 相关文章推荐
键盘控制事件应用教程大全
Nov 24 Javascript
javascript 播放器 控制
Jan 22 Javascript
JQuery Ajax 跨域访问的解决方案
Mar 12 Javascript
JS 模态对话框和非模态对话框操作技巧汇总
Apr 15 Javascript
一个JavaScript操作元素定位元素的实例
Oct 29 Javascript
node.js中的events.emitter.once方法使用说明
Dec 10 Javascript
js随机生成网页背景颜色的方法
Feb 26 Javascript
基于canvas实现的绚丽圆圈效果完整实例
Jan 26 Javascript
javascript冒泡排序小结
Apr 10 Javascript
基于javascript实现精确到毫秒的倒计时限时抢购
Apr 17 Javascript
javascript实现的全国省市县无刷新多级关联菜单效果代码
Aug 01 Javascript
JS 对java返回的json格式的数据处理方法
Dec 05 Javascript
基于JavaScript实现TAB标签效果
Jan 12 #Javascript
JavaScript实现瀑布流布局
Jun 28 #Javascript
轻松实现JavaScript图片切换
Jan 12 #Javascript
jQuery动画效果图片轮播特效
Jan 12 #Javascript
jQuery动画效果实现图片无缝连续滚动
Jan 12 #Javascript
jqueryMobile使用示例分享
Jan 12 #Javascript
WordPress中鼠标悬停显示和隐藏评论及引用按钮的实现
Jan 12 #Javascript
You might like
PHP编程中八种常见的文件操作方式
2006/11/19 PHP
PHP文件上传主要代码讲解
2013/09/30 PHP
php计算税后工资的方法
2015/07/28 PHP
HTML IMG标签 onload 内存溢出导致浏览器CPU占用过高
2021/03/09 Javascript
测试JavaScript字符串处理性能的代码
2009/12/07 Javascript
jquery 隐藏与显示tr标签示例代码
2014/06/06 Javascript
jQuery实现表格展开与折叠的方法
2015/05/04 Javascript
JavaScript统计网站访问次数的实现代码
2015/11/18 Javascript
使用postMesssage()实现跨域iframe页面间的信息传递方法
2016/03/29 Javascript
jquery实现刷新随机变化样式特效(tag标签样式)
2017/02/03 Javascript
详解angularjs中的隔离作用域理解以及绑定策略
2017/05/31 Javascript
js案例之鼠标跟随jquery版(实例讲解)
2017/07/21 jQuery
vue+swiper实现组件化开发的实例代码
2017/10/26 Javascript
JavaScript数组push方法使用注意事项
2017/10/30 Javascript
Vue表单demo v-model双向绑定问题
2018/06/29 Javascript
微信小程序实现获取小程序码和二维码java接口开发
2019/03/29 Javascript
bootstrap-table+treegrid实现树形表格
2019/07/26 Javascript
linux服务器快速卸载安装node环境(简单上手)
2021/02/22 Javascript
python读取注册表中值的方法
2013/04/08 Python
Python中设置变量作为默认值时容易遇到的错误
2015/04/03 Python
在Python中使用M2Crypto模块实现AES加密的教程
2015/04/08 Python
python队列通信:rabbitMQ的使用(实例讲解)
2017/12/22 Python
Python+OpenCV实现车牌字符分割和识别
2018/03/31 Python
python 获取毫秒数,计算调用时长的方法
2019/02/20 Python
PyQt5重写QComboBox的鼠标点击事件方法
2019/06/25 Python
基于python代码批量处理图片resize
2020/06/04 Python
python numpy库np.percentile用法说明
2020/06/08 Python
python中绕过反爬虫的方法总结
2020/11/25 Python
泰国网上购物:Shopee泰国
2018/09/14 全球购物
最好的意大利皮夹克:D’Arienzo
2018/12/04 全球购物
《手指教学》反思
2014/02/14 职场文书
给全校老师的建议书
2014/03/13 职场文书
青年教师师德演讲稿
2014/08/26 职场文书
酒店工程部主管岗位职责
2015/04/16 职场文书
标枪加油稿
2015/07/22 职场文书
js作用域及作用域链工作引擎
2022/07/07 Javascript