学习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 相关文章推荐
了解jQuery技巧来提高你的代码
Jan 08 Javascript
jquery让返回的内容显示在特定div里(代码少而精悍)
Jun 23 Javascript
jQuery ready()和onload的加载耗时分析
Sep 08 Javascript
vuex实现简易计数器
Oct 27 Javascript
JS经典正则表达式笔试题汇总
Dec 15 Javascript
为JQuery EasyUI 表单组件增加焦点切换功能的方法
Apr 13 jQuery
详解Node全局变量global模块
Sep 28 Javascript
Vue 中使用vue2-highcharts实现top功能的示例
Mar 05 Javascript
jquery实现动态添加附件功能
Oct 23 jQuery
React 全自动数据表格组件——BodeGrid的实现思路
Jun 12 Javascript
Angular8基础应用之表单及其验证
Aug 11 Javascript
编写v-for循环的技巧汇总
Dec 01 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
配置支持SSI
2006/11/25 PHP
常见的四种POST 提交数据方式(小总结)
2015/10/08 PHP
Redis使用Eval多个键值自增的操作实例
2016/11/04 PHP
php中Ioc(控制反转)和Di(依赖注入)
2017/05/07 PHP
TP3.2.3框架文件上传操作实例详解
2020/01/23 PHP
jQuery1.5.1 animate方法源码阅读
2011/04/05 Javascript
jquery 关于event.target使用的几点说明介绍
2013/04/26 Javascript
javascript对话框使用方法(警告框 javascript确认框 提示框)
2014/01/07 Javascript
js检验密码强度(低中高)附图
2014/06/05 Javascript
jquery滚动加载数据的方法
2015/03/09 Javascript
JavaScript仿百度图片浏览效果
2016/11/23 Javascript
详解Vue用axios发送post请求自动set cookie
2017/05/10 Javascript
JavaScript中附件预览功能实现详解(推荐)
2017/08/15 Javascript
JavaScript中Object值合并方法详解
2017/12/22 Javascript
jquery多级树形下拉菜单的实例代码
2019/07/09 jQuery
JS实现网页端猜数字小游戏
2020/03/06 Javascript
[55:48]VGJ.S vs TNC Supermajor 败者组 BO3 第二场 6.6
2018/06/07 DOTA
python实现飞机大战微信小游戏
2020/03/21 Python
win7 x64系统中安装Scrapy的方法
2018/11/18 Python
利用anaconda保证64位和32位的python共存
2021/03/09 Python
python集合是否可变总结
2019/06/20 Python
python中class的定义及使用教程
2019/09/18 Python
python 中的paramiko模块简介及安装过程
2020/02/29 Python
Python趣味实例,实现一个简单的抽奖刮刮卡
2020/07/18 Python
tensorflow基于CNN实战mnist手写识别(小白必看)
2020/07/20 Python
python脚本使用阿里云slb对恶意攻击进行封堵的实现
2021/02/04 Python
html5 localStorage本地存储_动力节点Java学院整理
2017/07/06 HTML / CSS
html5之Canvas路径绘图、坐标变换应用实例
2012/12/26 HTML / CSS
英国第一家领先的在线处方眼镜零售商:Glasses Direct
2018/02/23 全球购物
宏碁西班牙官网:Acer西班牙
2021/01/08 全球购物
Linux的主要特性
2014/10/06 面试题
建筑装饰学院室内设计专业个人自我评价
2013/12/07 职场文书
大学生涯自我鉴定
2014/01/16 职场文书
护士自我鉴定总结
2014/03/24 职场文书
国庆节主题班会
2015/08/15 职场文书
2016年6月份红领巾广播稿
2015/12/21 职场文书