学习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 相关文章推荐
接收键盘指令的脚本
Jun 26 Javascript
BOM与DOM的区别分析
Oct 26 Javascript
让人印象深刻的10个jQuery手风琴效果应用
May 08 Javascript
AngularJs表单验证实例代码解析
Nov 29 Javascript
Ionic3实现图片瀑布流布局
Aug 09 Javascript
微信小程序实战篇之购物车的实现代码示例
Nov 30 Javascript
vue init失败简单解决方法(终极版)
Dec 22 Javascript
JS使用tween.js动画库实现轮播图并且有切换功能
Jul 17 Javascript
React 无状态组件(Stateless Component) 与高阶组件
Aug 14 Javascript
angular 数据绑定之[]和{{}}的区别
Sep 25 Javascript
微信小程序登陆注册功能的实现代码
Dec 10 Javascript
详解ES6新增字符串扩张方法includes()、startsWith()、endsWith()
May 12 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《神奇女侠2》因疫情推迟上映 温子仁新恐怖片《恶性》撤档
2020/04/09 欧美动漫
php 中文和编码判断代码
2010/05/16 PHP
php加密解密实用类分享
2014/01/07 PHP
php如何解决无法上传大于8M的文件问题
2014/03/10 PHP
kohana框架上传文件验证规则写法示例
2014/07/14 PHP
PHP中使用Session配合Javascript实现文件上传进度条功能
2014/10/15 PHP
php获取网站百度快照日期的方法
2015/07/29 PHP
PHP中加速、缓存扩展的区别和作用详解(eAccelerator、memcached、xcache、APC )
2016/07/09 PHP
PHP 极验验证码实例讲解
2016/09/29 PHP
PHP将数据导出Excel表中的实例(投机型)
2017/07/31 PHP
firefox浏览器下javascript 拖动层效果与原理分析代码
2007/12/04 Javascript
javascript实现跳转菜单的具体方法
2013/07/05 Javascript
Jquery实现仿腾讯微博发表广播
2014/11/17 Javascript
javascript中的五种基本数据类型
2015/08/26 Javascript
jQuery实现的简洁下拉菜单导航效果代码
2015/08/26 Javascript
JS基于Ajax实现的网页Loading效果代码
2015/10/27 Javascript
JS动态添加选项案例分析
2016/10/17 Javascript
简单易懂的天气插件(代码分享)
2017/02/04 Javascript
Nodejs实现短信验证码功能
2017/02/09 NodeJs
Vue异步加载about组件
2017/10/31 Javascript
vue addRoutes实现动态权限路由菜单的示例
2018/05/15 Javascript
ES6中字符串的使用方法扩展
2019/06/04 Javascript
JavaScript cookie原理及使用实例
2020/05/08 Javascript
VUE : vue-cli中去掉路由中的井号#操作
2020/09/04 Javascript
Python用csv写入文件_消除空余行的方法
2018/07/06 Python
解决新版Pycharm中Matplotlib图像不在弹出独立的显示窗口问题
2019/01/15 Python
python实现自动解数独小程序
2019/01/21 Python
中专生毕业自我鉴定
2013/11/01 职场文书
入学申请自荐信范文
2014/02/26 职场文书
给校长的建议书
2014/03/12 职场文书
法英专业大学生职业生涯规划范文:衡外情,量己力!
2014/09/23 职场文书
2014小学年度工作总结
2014/12/20 职场文书
全陪导游词开场白
2015/05/29 职场文书
人民币使用说明书
2019/04/17 职场文书
如何用python反转图片,视频
2021/04/24 Python
MySQL数据库索引的最左匹配原则
2021/11/20 MySQL