学习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 相关文章推荐
js中如何把字符串转化为对象、数组示例代码
Jul 17 Javascript
jQuery插件实现表格隔行换色且感应鼠标高亮行变色
Sep 22 Javascript
jQuery使用$.get()方法从服务器文件载入数据实例
Mar 25 Javascript
javascript编写贪吃蛇游戏
Jul 07 Javascript
js时间戳转为日期格式的方法
Dec 28 Javascript
angular 用拦截器统一处理http请求和响应的方法
Jun 08 Javascript
js禁止浏览器页面后退功能的实例(推荐)
Sep 01 Javascript
微信小程序Getuserinfo解决方案图解
Aug 24 Javascript
React 组件渲染和更新的实现代码示例
Feb 21 Javascript
JS 遍历 json 和 JQuery 遍历json操作完整示例
Nov 11 jQuery
详解为element-ui的Select和Cascader添加弹层底部操作按钮
Feb 07 Javascript
5种 JavaScript 方式实现数组扁平化
Oct 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
DC游戏Steam周三特惠 《蝙蝠侠》阿卡姆系列平史低
2020/04/09 欧美动漫
PHP与javascript对多项选择的处理
2006/10/09 PHP
PHP实现域名whois查询的代码(数据源万网、新网)
2010/02/22 PHP
PHP编程最快明白(第一讲 软件环境和准备工作)
2010/10/25 PHP
ThinkPHP让分页保持搜索状态的方法
2014/07/02 PHP
PHP结合jquery ajax实现上传多张图片,并限制图片大小操作示例
2019/03/01 PHP
PHP+fiddler抓包采集微信文章阅读数点赞数的思路详解
2019/12/20 PHP
JQuery的Alert消息框插件使用介绍
2010/10/09 Javascript
jQuery $.get 的妙用 访问本地文本文件
2012/07/12 Javascript
nodeType属性返回被选节点的节点类型介绍
2013/11/22 Javascript
JavaScript中的console.dir()函数介绍
2014/12/29 Javascript
jQuery插件StickUp实现网页导航置顶
2015/04/12 Javascript
文字垂直滚动之javascript代码
2015/07/29 Javascript
js实现适用于素材网站的黑色多级菜单导航条效果
2015/08/24 Javascript
谈谈javascript中使用连等赋值操作带来的问题
2015/11/26 Javascript
Javascript Function.prototype.bind详细分析
2016/12/29 Javascript
Vuex 快速入门(简单易懂)
2018/09/20 Javascript
如何使用proxy实现一个简单完整的MVVM库的示例代码
2019/09/17 Javascript
[01:50]WODOTA制作 DOTA2中文宣传片《HERO》
2013/04/28 DOTA
python连接MySQL、MongoDB、Redis、memcache等数据库的方法
2013/11/15 Python
python使用cStringIO实现临时内存文件访问的方法
2015/03/26 Python
Python判断文件和文件夹是否存在的方法
2015/05/21 Python
python实现爬虫统计学校BBS男女比例之数据处理(三)
2015/12/31 Python
Python实现将json文件中向量写入Excel的方法
2018/03/26 Python
Django choices下拉列表绑定实例
2020/03/13 Python
解决jupyter notebook import error但是命令提示符import正常的问题
2020/04/15 Python
jupyter notebook tensorflow打印device信息实例
2020/04/20 Python
香港连卡佛百货官网:Lane Crawford
2019/09/04 全球购物
巴西本土电商平台:Americanas
2020/06/21 全球购物
经济管理专业自荐信
2013/12/30 职场文书
科技之星事迹材料
2014/06/02 职场文书
运动会方队口号
2014/06/07 职场文书
2014年职称评定工作总结
2014/11/26 职场文书
天堂的孩子观后感
2015/06/11 职场文书
几款流行的HTML5 UI框架比较(小结)
2021/04/08 HTML / CSS
mysql序号rownum行号实现方式
2022/12/24 MySQL