学习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 相关文章推荐
JavaScript高级程序设计(第3版)学习笔记3 js简单数据类型
Oct 11 Javascript
javascript中加号(+)操作符的一些神奇作用
Jun 06 Javascript
JS实现队列与堆栈的方法
Apr 21 Javascript
简单实现轮播图效果的实例
Jul 15 Javascript
jQuery fadeOut 异步实例代码详解
Aug 18 Javascript
百度地图JavascriptApi Marker平滑移动及车头指向行径方向
Mar 13 Javascript
原生javascript实现连连看游戏
Jan 03 Javascript
elementUI Tree 树形控件的官方使用文档
Apr 25 Javascript
微信小程序实现写入读取缓存详解
Aug 30 Javascript
vue之debounce属性被移除及处理详解
Nov 13 Javascript
js刷新页面location.reload()用法详解
Dec 09 Javascript
Openlayers实现距离面积测量
Sep 28 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安全下载文件的方法
2016/04/07 PHP
解析PHP之提取多维数组指定列的方法
2017/01/03 PHP
PHP实现的日历功能示例
2018/09/01 PHP
详解php中curl返回false的解决办法
2019/03/18 PHP
Js之软键盘实现(js源码)
2007/01/30 Javascript
js 链式延迟执行DOME
2012/01/04 Javascript
jquery封装的对话框简单实现
2013/07/21 Javascript
鼠标拖拽移动子窗体的JS实现
2014/02/25 Javascript
javascript常用正则表达式汇总
2015/07/31 Javascript
javascript常用的方法整理
2015/08/20 Javascript
Javascript中作用域的详细介绍
2016/10/06 Javascript
Bootstrap 响应式实用工具实例详解
2017/03/29 Javascript
vue.js使用watch监听路由变化的方法
2018/07/08 Javascript
vue中,在本地缓存中读写数据的方法
2018/09/21 Javascript
js实现unicode码字符串与utf8字节数据互转详解
2019/03/21 Javascript
vue中使用vue-pdf的方法详解
2020/09/05 Javascript
python分析网页上所有超链接的方法
2015/05/08 Python
理解生产者消费者模型及在Python编程中的运用实例
2016/06/26 Python
使用Python &amp; Flask 实现RESTful Web API的实例
2017/09/19 Python
python 获取list特定元素下标的实例讲解
2018/04/09 Python
如何利用Python分析出微信朋友男女统计图
2019/01/25 Python
YUV转为jpg图像的实现
2019/12/09 Python
春节到了 教你使用python来抢票回家
2020/01/06 Python
Python3爬虫中Ajax的用法
2020/07/10 Python
树莓派4B安装Tensorflow的方法步骤
2020/07/16 Python
浅谈matplotlib默认字体设置探索
2021/02/03 Python
悬挂训练绳:TRX
2017/12/14 全球购物
澳大利亚在线划船、露营和钓鱼商店:BCF Australia
2020/03/22 全球购物
学生会主席就职演讲稿
2014/01/14 职场文书
采购部经理岗位职责
2014/02/10 职场文书
《最可爱的人》教学反思
2014/02/14 职场文书
工程承诺书怎么写
2014/05/24 职场文书
经典禁毒标语
2014/06/16 职场文书
电子银行业务授权委托书
2014/10/10 职场文书
民主评议党员个人总结
2015/02/13 职场文书
python中如何对多变量连续赋值
2021/06/03 Python